| /******************************************************************************* |
| * 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; |
| } |
| } |