blob: 015135c8c456c28f0b35eddce138df41b97b0e93 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 Innoopract Informationssysteme GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Innoopract Informationssysteme GmbH - initial API and implementation
******************************************************************************/
package org.eclipse.epp.wizard.internal;
import java.io.File;
import java.net.URL;
import org.apache.log4j.Logger;
import org.eclipse.epp.wizard.model.EPPModel;
/**
* Cache for model data, so it does not have to be parsed for each session, but
* still is up to date.
*
* @author mwoelker
*/
public class ModelCache {
private static final String EPPMODEL_XML_FILENAME = "eppmodel.xml";
static Logger logger = Logger.getLogger( ModelCache.class );
private Object LOCK = new Object();
private Configuration configuration;
private EPPModel model;
private long UPDATE_CHECK_IN_SEC = 10;
private long UPDATE_INTERVAL_IN_SEC = 60 * 60; // hourly
private long ERROR_UPDATE_INTERVAL_IN_SEC = 1;
private long lastUpdate = 0;
/**
* This updater Thread runs in the background to keep model information
* up-to-date during the lifetime of the application Three intervals are used:
* UPDATE_CHECK_IN_SEC - used for checking the modification date on the
* eppmodel.xml file, model is reload if changed UPDATE_INTERVAL_IN_SEC -
* model is reloaded in this interval, regardless of modification timestamps,
* picks up changes in the upstream P2 Metadata repositories
* ERROR_UPDATE_INTERVAL_IN_SEC - This interval kicks in if the update fails,
* e.g. when the network is down
*
* @author mwoelker
*/
protected class ModelUpdater implements Runnable {
public void run() {
File modelDirectory = configuration.getModelDirectory();
File modelXML = new File( modelDirectory, EPPMODEL_XML_FILENAME );
long lastModified = 0;
while( true ) {
try {
long newLastModified = modelXML.lastModified();
if( lastModified != newLastModified ) {
reload();
lastModified = newLastModified;
}
if( lastUpdate + ( UPDATE_INTERVAL_IN_SEC * 1000 ) < System.currentTimeMillis() )
{
reload();
}
sleep( UPDATE_CHECK_IN_SEC );
} catch( Throwable t ) {
logger.error( "Error updating model", t );
sleep( ERROR_UPDATE_INTERVAL_IN_SEC );
}
}
}
/**
* reloads the model and updates the internal member variable
*
* @throws Exception
*/
private void reload() throws Exception {
EPPModel tempModel = loadModel();
synchronized( LOCK ) {
model = tempModel;
lastUpdate = System.currentTimeMillis();
}
logger.info( "Updated model" );
}
private void sleep( long timeInSec ) {
try {
Thread.sleep( timeInSec * 1000 );
} catch( InterruptedException e ) {
Thread.currentThread().interrupt();
}
}
}
public ModelCache( Configuration configuration ) {
super();
this.configuration = configuration;
Thread updateThread = new Thread( new ModelUpdater() );
updateThread.setName( "EPP Model updater" );
updateThread.setDaemon( true );
updateThread.start();
}
public EPPModel getModel() throws Exception {
synchronized( LOCK ) {
if( model == null ) {
model = loadModel();
}
return model;
}
}
protected EPPModel loadModel() throws Exception {
File modelDirectory = configuration.getModelDirectory();
File modelXML = new File( modelDirectory, EPPMODEL_XML_FILENAME );
EPPModel model = null;
model = EPPModel.read( modelXML.toURI().toURL(),
new URL( configuration.getEppMetadataRepository() ) );
return model;
}
}