/******************************************************************************* * 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.meta; import java.io.File; import java.util.Collection; import java.util.Iterator; import java.util.Vector; import java.util.prefs.Preferences; import org.eclipse.persistence.tools.workbench.scplugin.SCPlugin; import org.eclipse.persistence.tools.workbench.utility.AbstractModel; import org.eclipse.persistence.tools.workbench.utility.io.FileTools; import org.eclipse.persistence.tools.workbench.utility.string.StringTools; /** * This manager takes care to handle {@link SCSessionsProperties}, which are * objects containing design information that are not persisted into the * sessions.xml. A copy is always returned in order to not persist unsaved * properties. When it is time to save the extra information for a newly saved * sessions.xml, {@link #update(SCSessionsProperties)} needs to be called. * * @version 10.1.3 * @author Pascal Filion */ public final class SCSessionsPropertiesManager extends AbstractModel { /** * Holds onto the preferences to retrieve the default Sessions Configuration * name (eg: sessions). */ private final Preferences preferences; /** * The <code>Collection</code> of {@link SCSessionsPropertiesManager}. */ private Collection sessionsProperties; /** * The list of unsaved file names. */ private Collection unsavedSessionsFileNames; /** * The file name to be used for untitled sessions.xml, which is "sessions". */ public static final String UNTITLED_FILE_NAME = "sessions"; /** * Creates a new <code>SCSessionsPropertiesManager</code>. * * @param preferences The parent node where the classpath node is located */ public SCSessionsPropertiesManager(Preferences preferences) { super(); this.preferences = preferences.node("classpath"); read(); } /** * Creates a new <code>SCSessionsProperties</code> that will contains the * class repository information for the sessions.xml located at the given * path. * * @param path The location of the sessions.xml to be created * @param classpath The classpath entries * @return A new {@link SCSessionsProperties} */ SCSessionsProperties addSessionsProperties(File path, String[] classpath, int index) { SCSessionsProperties properties = buildSessionsProperties(path, classpath, index); properties.manager = this; this.sessionsProperties.add(properties); return properties; } /** * Adds the given <code>SCSessionsProperties</code> to this manager. * * @param properties The <code>SCSessionsProperties</code> to be added */ void addSessionsProperties(SCSessionsProperties properties) { if (!this.sessionsProperties.contains(properties)) { this.sessionsProperties.add(properties); } } /** * Creates a new <code>SCSessionsProperties</code> that will contains the * class repository information for the sessions.xml located at the given * path. * * @param path The location of the sessions.xml to be created * @param classpath The classpath entries * @return A new {@link SCSessionsProperties} */ private SCSessionsProperties buildSessionsProperties(File path, String[] classpath, int index) { return new SCSessionsProperties(this, path, classpath, index); } /** * Retrieves the <code>SCSessionsProperties</code> that contains the class * repository information for the sessions.xml located at the given path. * * @param path The path of the sessions.xml to retrieve its class repository * information * @return A copy of the original <code>SCSessionsProperties</code> that will * be required to be saved through {@link #update(SCSessionsProperties)} when * the file will be saved */ public SCSessionsProperties getSessionsProperties(File path) { for (Iterator iter = sessionsProperties(); iter.hasNext(); ) { SCSessionsProperties properties = (SCSessionsProperties) iter.next(); if (properties.getPath().equals(path)) { return properties; } } // Keep a history of the file name, only for untitled file if (path.getPath().startsWith(untitledFileName())) { this.unsavedSessionsFileNames.add(path); } // This one will not be encapsulated until update() is called for it return buildSessionsProperties(path, new String[0], -1); } /** * Initializes this <code>SCSessionsPropertiesManager</code>. */ protected void initialize() { super.initialize(); this.sessionsProperties = new Vector(); this.unsavedSessionsFileNames = new Vector(); } /** * Returns the next untitled file name for a sessions.xml, the name will be * "Sessions1.xml", then "Sessions2.xml" and so on. * * @return A non-fully qualified file name with this format SesssionX.xml * where X is the next number of untitled sessions.xml that was created */ public File nextUntitledSessionsFile() { String defaultUntitledFileName = untitledFileName(); boolean firstUntitledUsed = false; int index = 0; for (Iterator iter = unsavedSessionsFileNames(); iter.hasNext(); ) { File file = (File) iter.next(); String fileName = FileTools.stripExtension(file.getPath()); if (fileName.startsWith(defaultUntitledFileName)) { String remaining = fileName.substring(defaultUntitledFileName.length(), fileName.length()); try { if (remaining.length() == 0) { firstUntitledUsed = true; index++; } else { index = Math.max(new Integer(remaining).intValue(), index); } } catch (Exception e) { // Valid exception, what is after sessions is not a number } } } StringBuffer sb = new StringBuffer(13); sb.append(defaultUntitledFileName); if (firstUntitledUsed) // sessions0.xml is used as sessions.xml sb.append(++index); // ++index to get the next available index sb.append(".xml"); return new File(sb.toString()); } /** * Changes the location of the sessions.xml of the original <code>SCSessionsProperties</code>. * * @param properties The copy where the path has been changed */ public void pathChanged(final SCSessionsProperties properties) { SCSessionsProperties original = null; File path = properties.getPath(); for (Iterator iter = sessionsProperties(); iter.hasNext(); ) { SCSessionsProperties nextProperties = (SCSessionsProperties) iter.next(); if ((properties != nextProperties) && nextProperties.getPath().equals(path)) { original = nextProperties; break; } } // The new original will be recreated on save if (original != null) { this.sessionsProperties.add(properties); this.sessionsProperties.remove(original); } } /** * Reads the properties for all sessions.xml files that were edited in the * Mapping Workbench. * * @return The root object containing all the information about the classpath * for any sessions.xml that was edited */ private void read() { // Attempt to load the manager try { String[] keys = this.preferences.keys(); for (int index = 0; index < keys.length; index++) { String key = keys[index]; // 10.1.3.x format // location_X = path // classpath_x = classpath if (key.startsWith(SCSessionsProperties.LOCATION_TAG)) { int underscoreIndex = key.indexOf("_"); int entryIndex = Integer.valueOf(key.substring(underscoreIndex + 1)).intValue(); String fileName = this.preferences.get(key, null); String classpath = this.preferences.get(SCSessionsProperties.CLASSPATH_TAG + entryIndex, null); if ((fileName.length() > 0) && !StringTools.stringIsEmpty(classpath)) { String[] classpathEntries = classpath.split(File.pathSeparator); addSessionsProperties(new File(fileName), classpathEntries, entryIndex); } } // 10.1.3.0.0 format // path = classpath else if (!key.startsWith(SCSessionsProperties.CLASSPATH_TAG)) { String classpath = this.preferences.get(key, null); if ((key.length() > 0) && !StringTools.stringIsEmpty(classpath)) { String[] classpathEntries = classpath.split(File.pathSeparator); SCSessionsProperties properties = addSessionsProperties(new File(key), classpathEntries, -1); // Convert to the new format properties.save(this.preferences.parent()); // Remove the old format this.preferences.remove(key); } } } } catch (Exception e) { // Ignore and simply have no classpath information } } /** * Returns an <code>Iterator</code> over the <code>SCSessionsProperties</code> * that were loaded. * * @return The iterator of <code>SCSessionsProperties</code> */ private Iterator sessionsProperties() { return this.sessionsProperties.iterator(); } /** * Returns a String representation of this <code>SCSessionsProperties</code>. * * @return The short description of this class and its values */ public final String toString() { StringBuffer sb = new StringBuffer(); StringTools.buildSimpleToStringOn(this, sb); sb.append(" ("); toString(sb); sb.append(')'); return sb.toString(); } /** * Appends more information about this <code>SCSessionsProperties</code> to * the given buffer. * * @param buffer The buffer used to add extra information */ public void toString(StringBuffer buffer) { buffer.append(", sessions="); buffer.append(this.sessionsProperties); } /** * Returns an <code>Iterator</code> over the file name of untitled * sessions.xml that were created. * * @return The iterator over a collection of <code>File</code>s */ private Iterator unsavedSessionsFileNames() { return this.unsavedSessionsFileNames.iterator(); } /** * Retrieves the default name to be used for the Sessions Configuration file * * @return The default name to be used for the Sessions Configuration file or * {@link #UNTITLED_FILE_NAME} if the preferences does not have any value set */ private String untitledFileName() { return this.preferences.parent().get(SCPlugin.NEW_NAME_SESSIONS_CONFIGURATION_PREFERENCE, UNTITLED_FILE_NAME); } }