/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.fps;
import java.io.File;
import java.io.IOException;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.lib.cvsclient.Client;
import org.netbeans.lib.cvsclient.admin.Entry;
import org.netbeans.lib.cvsclient.admin.StandardAdminHandler;
import org.netbeans.lib.cvsclient.command.CommandAbortedException;
import org.netbeans.lib.cvsclient.command.CommandException;
import org.netbeans.lib.cvsclient.command.DefaultFileInfoContainer;
import org.netbeans.lib.cvsclient.command.GlobalOptions;
import org.netbeans.lib.cvsclient.command.checkout.CheckoutCommand;
import org.netbeans.lib.cvsclient.command.update.UpdateCommand;
import org.netbeans.lib.cvsclient.connection.AbstractConnection;
import org.netbeans.lib.cvsclient.connection.AuthenticationException;
import org.netbeans.lib.cvsclient.event.CVSAdapter;
import org.netbeans.lib.cvsclient.event.EnhancedMessageEvent;
import org.netbeans.lib.cvsclient.event.FileInfoEvent;
import org.netbeans.lib.cvsclient.event.FileUpdatedEvent;
import org.netbeans.lib.cvsclient.event.MessageEvent;
import org.openflexo.foundation.Inspectors;
import org.openflexo.fps.dm.CVSFileDiscovered;
import org.openflexo.fps.dm.CVSFileForgotten;
import org.openflexo.fps.dm.CVSModuleDiscovered;
import org.openflexo.fps.dm.CVSModuleForgotten;
import org.openflexo.fps.dm.HasCVSExplored;
import org.openflexo.fps.dm.WillCVSExplore;
public class CVSModule extends FPSObject implements CVSExplorable {
private static final Logger logger = Logger.getLogger(CVSModule.class.getPackage().getName());
private String _moduleName;
private CVSExplorable _parent;
protected CVSModule(String moduleName, CVSExplorable parent) {
super();
if (logger.isLoggable(Level.FINE)) {
logger.fine("Created module " + this + " (" + moduleName + ") parent=" + parent);
}
_moduleName = moduleName;
_parent = parent;
_modules = new Vector<CVSModule>();
_files = new Vector<CVSFile>();
}
@Override
public CVSExplorable getParent() {
return _parent;
}
public String getModuleName() {
return _moduleName;
}
public String getFullQualifiedModuleName() {
if (getParent() instanceof CVSRepository) {
return getModuleName();
} else if (getParent() instanceof CVSModule) {
return ((CVSModule) getParent()).getFullQualifiedModuleName() + '/' + getModuleName();
}
return null;
}
public boolean isSubModule() {
return !(getParent() instanceof CVSRepository);
}
@Override
public String getInspectorName() {
return Inspectors.FPS.CVS_MODULE_INSPECTOR;
}
@Override
public String getClassNameKey() {
return "cvs_module";
}
@Override
public CVSRepository getCVSRepository() {
if (_parent instanceof CVSRepository) {
return (CVSRepository) _parent;
} else {
return _parent.getCVSRepository();
}
}
@Override
public boolean isContainedIn(FPSObject obj) {
if (obj instanceof CVSRepositoryList) {
return getCVSRepository().isContainedIn(obj);
} else if (obj instanceof CVSRepository) {
return getCVSRepository() == obj;
}
return obj == this;
}
private Vector<CVSModule> _modules;
@Override
public Vector<CVSModule> getCVSModules() {
return _modules;
}
public void setCVSModules(Vector<CVSModule> modules) {
_modules = modules;
setChanged();
}
public void addToCVSModules(CVSModule module) {
_modules.add(module);
setChanged();
notifyObservers(new CVSModuleDiscovered(module));
}
public void removeFromCVSModules(CVSModule module) {
_modules.remove(module);
setChanged();
notifyObservers(new CVSModuleForgotten(module));
}
public CVSModule getModuleNamed(String name) {
if (name.indexOf('/') > -1) {
String parentModuleName = name.substring(0, name.lastIndexOf('/'));
CVSModule parentModule = getModuleNamed(parentModuleName);
return parentModule.getModuleNamed(name.substring(name.lastIndexOf('/') + 1));
}
for (CVSModule module : _modules) {
if (module.getModuleName().equals(name)) {
return module;
}
}
// Not found, create it
CVSModule returned;
logger.info("Create module " + name + " as child of module " + this.getFullQualifiedModuleName());
addToCVSModules(returned = new CVSModule(name, this));
return returned;
}
private Vector<CVSFile> _files;
public Vector<CVSFile> getCVSFiles() {
return _files;
}
public void setCVSFiles(Vector<CVSFile> modules) {
_files = modules;
setChanged();
}
public void addToCVSFiles(CVSFile module) {
_files.add(module);
setChanged();
notifyObservers(new CVSFileDiscovered(module));
}
public void removeFromCVSFiles(CVSFile module) {
_files.remove(module);
setChanged();
notifyObservers(new CVSFileForgotten(module));
}
private CVSExplorer _explorer;
@Override
public CVSExplorer getCVSExplorer(CVSExplorerListener explorerListener) {
if (_explorer == null) {
_explorer = new CVSExplorer(this, explorerListener);
}
return _explorer;
}
public CVSExplorer exploreModule(CVSExplorerListener explorerListener) {
_explorer = null;
CVSExplorer returned = getCVSExplorer(explorerListener);
returned.explore();
return returned;
}
@Override
public void notifyWillExplore() {
setChanged();
notifyObservers(new WillCVSExplore());
}
@Override
public void notifyHasExplored() {
setChanged();
notifyObservers(new HasCVSExplored());
}
private class ModuleRetriever extends CVSAdapter {
private Vector<CVSModule> _knownModules;
private Vector<CVSFile> _knownFiles;
private StandardAdminHandler adminHandler;
private ModuleRetriever(Vector<CVSModule> knownModules, Vector<CVSFile> knownFiles) {
_knownModules = knownModules;
_knownFiles = knownFiles;
adminHandler = new StandardAdminHandler();
}
/**
* Called when the server wants to send a message to be displayed to the user. The message is only for information purposes and
* clients can choose to ignore these messages if they wish.
*
* @param e
* the event
*/
@Override
public void messageSent(MessageEvent e) {
// logger.info("**** messageSent(MessageEvent) "+e+" "+e.getMessage());
if (e instanceof EnhancedMessageEvent) {
return;
} else {
int start = e.getMessage().indexOf("`");
int stop = e.getMessage().indexOf("'");
if (start >= 0 && stop >= start) {
String fullQualifiedModule = e.getMessage().substring(start + 1, stop);
if (!fullQualifiedModule.equals("CVSROOT")) {
// logger.info("Found "+foundModule+" ! Add it.");
CVSModule existingModule = null;
String foundModule = fullQualifiedModule.substring(fullQualifiedModule.lastIndexOf('/') + 1);
for (CVSModule m : _knownModules) {
if (m.getModuleName().equals(foundModule)) {
existingModule = m;
}
}
if (existingModule == null) {
addToCVSModules(new CVSModule(foundModule, CVSModule.this));
} else {
_knownModules.remove(existingModule);
}
}
}
}
}
/**
* Called when a file has been updated
*
* @param e
* the event
*/
@Override
public void fileUpdated(FileUpdatedEvent e) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("fileUpdated() " + e.getFilePath());
}
}
/**
* Called when file status information has been received
*/
@Override
public void fileInfoGenerated(FileInfoEvent e) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("fileInfoGenerated() " + e.getInfoContainer().getClass().getSimpleName() + " " + e.getInfoContainer());
}
if (e.getInfoContainer() instanceof DefaultFileInfoContainer) {
DefaultFileInfoContainer info = (DefaultFileInfoContainer) e.getInfoContainer();
if (logger.isLoggable(Level.FINE)) {
logger.fine("Added file : " + info.getFile());
}
CVSFile existingFile = null;
String foundFile = info.getFile().getName();
for (CVSFile f : _knownFiles) {
if (f.getFileName().equals(foundFile)) {
existingFile = f;
}
}
Entry entry = null;
try {
entry = adminHandler.getEntry(info.getFile());
if (logger.isLoggable(Level.FINE)) {
logger.fine("Entry for " + info.getFile() + ": " + entry);
}
} catch (IOException e1) {
logger.warning("Could not retrieve entry for " + info.getFile());
}
if (existingFile == null) {
addToCVSFiles(new CVSFile(info.getFile(), entry, null));
} else {
existingFile.setEntry(entry);
_knownFiles.remove(existingFile);
}
}
}
}
private File _repositoryExploringDirectory;
@Override
public File getRepositoryExploringDirectory() {
return _repositoryExploringDirectory;
}
private void _retrieveLocalFiles(ModuleRetriever retriever) throws IOException, CommandAbortedException, CommandException,
AuthenticationException {
if (logger.isLoggable(Level.FINE)) {
logger.fine("_retrieveLocalFiles() on directory " + getParent().getRepositoryExploringDirectory());
}
// Run "cvs checkout -l" command on parent directory
CheckoutCommand checkout = new CheckoutCommand();
checkout.setRecursive(false);
checkout.setModule(getFullQualifiedModuleName());
AbstractConnection connection = CVSConnection.initConnection(getCVSRepository());
GlobalOptions globalOptions = new GlobalOptions();
globalOptions.setCVSRoot(connection.getRepository());
Client client = new Client(connection, retriever.adminHandler);
client.setLocalPath(getCVSRepository().getRepositoryExploringDirectory().getCanonicalPath());
client.getEventManager().addCVSListener(retriever);
client.getEventManager().addCVSListener(CVSConsole.getCVSConsole());
CVSConsole.getCVSConsole().commandLog("cvs " + checkout.getCVSCommand());
logger.info("Command " + checkout.getCVSCommand());
try {
client.executeCommand(checkout, globalOptions);
} finally {
try {
client.getConnection().close();
} catch (IOException e) {
e.printStackTrace();
}
}
_repositoryExploringDirectory = new File(getParent().getRepositoryExploringDirectory(), getModuleName());
}
private void _retrieveLocalDirectories(ModuleRetriever retriever) throws IOException, CommandAbortedException, CommandException,
AuthenticationException {
if (logger.isLoggable(Level.FINE)) {
logger.fine("_retrieveLocalDirectories() on directory " + getParent().getRepositoryExploringDirectory());
}
// Run "cvs -n update -d" command on parent directory
UpdateCommand updt = new UpdateCommand();
updt.setBuildDirectories(true); // build directories '-d'
File[] files = new File[1];
files[0] = _repositoryExploringDirectory.getCanonicalFile();
updt.setFiles(files);
AbstractConnection connection = CVSConnection.initConnection(getCVSRepository());
GlobalOptions globalOptions = new GlobalOptions();
globalOptions.setDoNoChanges(true); // no changes on files '-n'
globalOptions.setCVSRoot(connection.getRepository());
Client client = new Client(connection, retriever.adminHandler);
client.setLocalPath(getParent().getRepositoryExploringDirectory().getCanonicalPath());
client.getEventManager().addCVSListener(retriever);
client.getEventManager().addCVSListener(CVSConsole.getCVSConsole());
CVSConsole.getCVSConsole().commandLog("cvs " + updt.getCVSCommand());
logger.info("Command " + updt.getCVSCommand());
try {
client.executeCommand(updt, globalOptions);
} finally {
try {
client.getConnection().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected void _retrieveSubModules() throws IOException, CommandAbortedException, CommandException, AuthenticationException {
Vector<CVSModule> knownModules = (Vector<CVSModule>) getCVSModules().clone();
Vector<CVSFile> knownFiles = (Vector<CVSFile>) getCVSFiles().clone();
ModuleRetriever retriever = new ModuleRetriever(knownModules, knownFiles);
_retrieveLocalFiles(retriever);
_retrieveLocalDirectories(retriever);
}
@Override
public String getFullyQualifiedName() {
return getFullQualifiedModuleName();
}
@Override
public CVSExplorer explore(CVSExplorerListener explorerListener) {
return exploreModule(explorerListener);
}
}