/*******************************************************************************
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.scplugin.model.adapter;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.util.List;
import java.util.prefs.Preferences;
import org.eclipse.persistence.tools.workbench.scplugin.model.meta.ClassRepository;
import org.eclipse.persistence.tools.workbench.scplugin.model.meta.SCSessionsProperties;
import org.eclipse.persistence.tools.workbench.utility.events.ChangeNotifier;
import org.eclipse.persistence.tools.workbench.utility.events.DefaultChangeNotifier;
import org.eclipse.persistence.tools.workbench.utility.io.FileTools;
import org.eclipse.persistence.internal.sessions.factories.XMLSessionConfigWriter;
import org.eclipse.persistence.internal.sessions.factories.model.SessionConfigs;
import org.eclipse.persistence.sessions.factories.SessionManager;
/**
* Abstract class for root Session Config adapter.
*
* @author Tran Le
*/
abstract class RootSCAdapter extends SCAdapter implements Nominative {
// property change
private volatile String name;
private volatile SessionManager sessionManager;
private volatile SCSessionsProperties properties;
private volatile Preferences preferences;
private volatile File savePath;
public final static String SAVE_PATH_PROPERTY = "configSavePath";
/** used to notifier listeners of changes */
private ChangeNotifier changeNotifier;
/** used to generate problems */
private volatile Validator validator;
/**
* Constructor for RootSCAdapter and load the config from file.
* @param buildModel
* true - creates a new config model
* false - load config model from file
*/
RootSCAdapter( SCSessionsProperties properties, Preferences preferences, boolean buildModel) {
super();
this.initialize( properties, preferences);
if( buildModel) {
this.initialize( this.buildModel());
this.initializeDefaults();
this.setConfigClean( true);
}
else {
this.initializeFromModel( this.load());
this.markEntireBranchClean();
this.postInitializationFromModel();
this.setConfigClean( false); // contains user's config
}
}
/**
* Subclasses should override this method to add their children
* to the specified collection.
* @see #children()
*/
protected void addChildrenTo(List children) {
super.addChildrenTo(children);
children.add(getClassRepository());
}
/**
* Initializes session manager.
*/
protected void initialize() {
super.initialize();
this.sessionManager = SessionManager.getManager();
}
/**
* Initialize sessions project properties.
*/
private void initialize( SCSessionsProperties properties, Preferences preferences) {
this.changeNotifier = DefaultChangeNotifier.instance();
validator = NULL_VALIDATOR;
this.properties = properties;
this.preferences = preferences;
this.savePath = properties.getPath();
setName( this.savePath.getName());
properties.getClassRepository().setParent(this);
}
private SessionConfigs load() {
SessionConfigs topLinkSessions =
this.sessionManager.getInternalMWConfigObjects( getPath().getPath(), buildLoader(), false);
return topLinkSessions;
}
private URL[] buildEntries() {
Iterator iter = getClassRepository().classpathEntries();
URL[] entries = new URL[ getClassRepository().classpathEntriesSize()];
int index = 0;
while( iter.hasNext()) {
try {
URL url = new URL( "file", "", ( String)iter.next());
entries[ index++] = url;
}
catch( MalformedURLException e) {
// Can skip an invalid entry, which should in theory never happen
}
}
return entries;
}
private ClassLoader buildLoader() {
URLClassLoader loader = new URLClassLoader( buildEntries(), getClass().getClassLoader()) {
public URL findResource( String name) {
try {
if( name.equals( getPath().getPath())) {
return getPath().toURL();
}
}
catch( MalformedURLException e) {
// Ignore so that super.findResource(String) will be called
}
URL url = super.findResource(name);
if( url != null)
return url;
// Use this class class loader
return getClass().getResource(name);
}
};
return loader;
}
public void save( File file) throws IOException {
this.setSavePath( file);
this.save();
}
public void save() throws IOException {
this.preSaving();
XMLSessionConfigWriter.write((SessionConfigs)this.getModel(), this.getPath().toString());
this.postSaving();
// Mark the whole tree as clean
markEntireBranchClean();
}
public String displayString() {
return this.name;
}
public File getPath() {
return this.properties.getPath();
}
public SCSessionsProperties getProperties() {
return properties;
}
/**
* Returns the Preferences node used by the SC.
*/
Preferences preferences() {
return preferences;
}
/**
* Returns the <code>ClassRepository</code> that should be used by the
* sessions.xml.
*
* @return The repository for classpath entries and classes
*/
public ClassRepository getClassRepository() {
return this.properties.getClassRepository();
}
public File getSaveDirectory() {
return this.properties.getPath().getParentFile();
}
/**
* if the save directory changes, we mark the entire
* project dirty so it is written out in the new directory
*/
private void setSavePath( File savePath) {
Object old = this.getSavePath();
this.savePath = savePath;
this.properties.pathChanged( savePath);
this.firePropertyChanged( SAVE_PATH_PROPERTY, old, savePath);
this.setName(savePath.getName());
}
private File getSavePath() {
return savePath;
}
private static final String CR = System.getProperty("line.separator");
public void toString( StringBuffer sb) {
sb.append( CR).append( "\t").append( this.displayString() + "( " + this.getConfigFileVersion()+ " )");
}
/**
* Returns this config model property.
*/
public String getName() {
return this.name;
}
/**
* Sets this config model property.
*/
private void setName( String name) {
Object old = this.getName();
this.name = FileTools.stripExtension( name);
this.firePropertyChanged( NAME_PROPERTY, old, name);
}
/**
* as the root node, we must implement this method
*/
public ChangeNotifier getChangeNotifier() {
return this.changeNotifier;
}
/**
* allow clients to install another change notifier
*/
public void setChangeNotifier(ChangeNotifier changeNotifier) {
this.changeNotifier = changeNotifier;
}
/**
* as the root node, we must implement this method
*/
public Validator getValidator() {
return validator;
}
/**
* allow clients to install an active validator
*/
public void setValidator(Validator validator) {
this.validator = validator;
}
/**
* Mark the object and all its descendants as clean.
* N/A to Root objects.
*/
protected void markEntireConfigurationClean() {
return;
}
}