/** * (C) Copyright 2013 Jabylon (http://www.jabylon.org) and others. * * 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 */ package org.jabylon.rest.ui.wicket.config.sections; import java.io.File; import java.util.Collection; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.attributes.AjaxCallListener; import org.apache.wicket.ajax.attributes.AjaxRequestAttributes; import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Button; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.IModel; import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.emf.cdo.CDOState; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.util.CommitException; import org.jabylon.common.progress.RunnableWithProgress; import org.jabylon.common.team.TeamProvider; import org.jabylon.common.team.TeamProviderException; import org.jabylon.common.team.TeamProviderUtil; import org.jabylon.common.util.FileUtil; import org.jabylon.common.util.PreferencesUtil; import org.jabylon.properties.Project; import org.jabylon.properties.ProjectVersion; import org.jabylon.properties.PropertiesPackage; import org.jabylon.properties.PropertyFileDiff; import org.jabylon.properties.ScanConfiguration; import org.jabylon.resources.persistence.PropertyPersistenceService; import org.jabylon.rest.ui.Activator; import org.jabylon.rest.ui.model.ComplexEObjectListDataProvider; import org.jabylon.rest.ui.model.ProgressionModel; import org.jabylon.rest.ui.util.WicketUtil; import org.jabylon.rest.ui.wicket.BasicPanel; import org.jabylon.rest.ui.wicket.components.ProgressPanel; import org.jabylon.rest.ui.wicket.components.ProgressShowingAjaxButton; import org.jabylon.rest.ui.wicket.config.AbstractConfigSection; import org.jabylon.rest.ui.wicket.config.SettingsPage; import org.jabylon.rest.ui.wicket.config.SettingsPanel; import org.jabylon.security.CommonPermissions; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ProjectVersionsConfigSection extends BasicPanel<Project> { private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(ProjectVersionsConfigSection.class); public ProjectVersionsConfigSection(String id, IModel<Project> model, Preferences config) { super(id, model); add(buildAddNewLink(model)); ComplexEObjectListDataProvider<ProjectVersion> provider = new ComplexEObjectListDataProvider<ProjectVersion>(model, PropertiesPackage.Literals.RESOLVABLE__CHILDREN); ListView<ProjectVersion> project = new ListView<ProjectVersion>("versions", provider) { private static final long serialVersionUID = 1L; private ProgressionModel progressModel; @Override protected void populateItem(ListItem<ProjectVersion> item) { item.setOutputMarkupId(true); item.add(new Label("name", item.getModelObject().getName())); item.add(new Label("summary", new StringResourceModel("ProjectVersionsConfigSection.summary", item, null, item.getModel().getObject().getChildren().size()))); progressModel = new ProgressionModel(""); final ProgressPanel progressPanel = new ProgressPanel("progress", progressModel); item.add(progressPanel); ProjectVersion projectVersion = item.getModelObject(); item.add(new BookmarkablePageLink<Void>("edit",SettingsPage.class,WicketUtil.buildPageParametersFor(projectVersion))); item.add(createCheckoutAction(progressPanel, item.getModel())); item.add(createRescanAction(progressPanel, item.getModel())); item.add(createUpdateAction(progressPanel, item.getModel())); item.add(createResetAction(progressPanel, item.getModel())); item.add(createCommitAction(progressPanel, item.getModel())); item.add(createDeleteAction(progressPanel, item.getModel())); } }; project.setReuseItems(true); project.setOutputMarkupId(true); add(project); } private Component buildAddNewLink(IModel<Project> model) { Project project = model.getObject(); if (project.cdoState() == CDOState.NEW || project.cdoState() == CDOState.TRANSIENT) { // it's a new project, we can't add anything yet Button link = new Button("addNew"); link.setEnabled(false); return link; } PageParameters parameters = WicketUtil.buildPageParametersFor(project); parameters.add(SettingsPanel.QUERY_PARAM_CREATE, PropertiesPackage.Literals.PROJECT_VERSION.getName()); return new BookmarkablePageLink<Void>("addNew", SettingsPage.class, parameters); } protected Component createDeleteAction(ProgressPanel progressPanel, final IModel<ProjectVersion> model) { Button button = new DeleteAction("delete", model, nls("ProjectVersionsConfigSection.delete.action.confirmation", model.getObject().getName())); button.setDefaultFormProcessing(false); return button; } protected Component createUpdateAction(ProgressPanel progressPanel, final IModel<ProjectVersion> model) { RunnableWithProgress runnable = new RunnableWithProgress() { private static final long serialVersionUID = 1L; @Override public IStatus run(IProgressMonitor monitor) { ProjectVersion version = model.getObject(); TeamProvider provider = TeamProviderUtil.getTeamProvider(version.getParent().getTeamProvider()); CDOTransaction transaction = Activator.getDefault().getRepositoryConnector().openTransaction(); try { version = transaction.getObject(version); SubMonitor subMonitor = SubMonitor.convert(monitor, "Updating", 100); Collection<PropertyFileDiff> updates = provider.update(version, subMonitor.newChild(50)); subMonitor.setWorkRemaining(updates.size() * 2); subMonitor.subTask("Processing updates"); for (PropertyFileDiff updatedFile : updates) { version.partialScan(PreferencesUtil.getScanConfigForProject(getModelObject()), updatedFile); subMonitor.worked(1); } subMonitor.setTaskName("Database Sync"); transaction.commit(subMonitor.newChild(updates.size())); } catch (TeamProviderException e) { logger.error("Update failed",e); return new Status(IStatus.ERROR, Activator.BUNDLE_ID, "Update failed",e); } catch (CommitException e) { logger.error("Failed to commit the transaction",e); return new Status(IStatus.ERROR, Activator.BUNDLE_ID, "Failed to commit the transaction",e); } finally { transaction.close(); PropertyPersistenceService persistenceService = Activator.getDefault().getPersistenceService(); if(persistenceService!=null) persistenceService.clearCache(); else logger.error("Could not obtain property persistence service"); } return Status.OK_STATUS; } }; return new ProgressShowingAjaxButton("update", progressPanel, runnable, nls("update.version.job.label",getModelObject().getName())) { private static final long serialVersionUID = 1L; public boolean isVisible() { ProjectVersion version = model.getObject(); TeamProvider provider = TeamProviderUtil.getTeamProvider(version.getParent().getTeamProvider()); if (provider == null) return false; File file = new File(version.absoluteFilePath().toFileString()); return (file.isDirectory()); }; }; } protected Component createResetAction(ProgressPanel progressPanel, final IModel<ProjectVersion> model) { RunnableWithProgress runnable = new RunnableWithProgress() { private static final long serialVersionUID = 1L; @Override public IStatus run(IProgressMonitor monitor) { ProjectVersion version = model.getObject(); TeamProvider provider = TeamProviderUtil.getTeamProvider(version.getParent().getTeamProvider()); CDOTransaction transaction = Activator.getDefault().getRepositoryConnector().openTransaction(); try { version = transaction.getObject(version); SubMonitor subMonitor = SubMonitor.convert(monitor, "Resetting", 100); Collection<PropertyFileDiff> updates = provider.reset(version, subMonitor.newChild(50)); subMonitor.setWorkRemaining(updates.size() * 2); subMonitor.subTask("Processing diff"); for (PropertyFileDiff updatedFile : updates) { version.partialScan(PreferencesUtil.getScanConfigForProject(getModelObject()), updatedFile); subMonitor.worked(1); } subMonitor.setTaskName("Database Sync"); transaction.commit(subMonitor.newChild(updates.size())); } catch (TeamProviderException e) { logger.error("Update failed",e); return new Status(IStatus.ERROR, Activator.BUNDLE_ID, "Reset failed",e); } catch (CommitException e) { logger.error("Failed to commit the transaction",e); return new Status(IStatus.ERROR, Activator.BUNDLE_ID, "Failed to commit the transaction",e); } finally { transaction.close(); PropertyPersistenceService persistenceService = Activator.getDefault().getPersistenceService(); if(persistenceService!=null) persistenceService.clearCache(); else logger.error("Could not obtain property persistence service"); } return Status.OK_STATUS; } }; return new ProgressShowingAjaxButton("reset", progressPanel, runnable, nls("reset.version.job.label",getModelObject().getName())) { private static final long serialVersionUID = 1L; public boolean isVisible() { ProjectVersion version = model.getObject(); TeamProvider provider = TeamProviderUtil.getTeamProvider(version.getParent().getTeamProvider()); if (provider == null) return false; File file = new File(version.absoluteFilePath().toFileString()); return (file.isDirectory()); }; }; } protected Component createCommitAction(ProgressPanel progressPanel, final IModel<ProjectVersion> model) { RunnableWithProgress runnable = new RunnableWithProgress() { private static final long serialVersionUID = 1L; @Override public IStatus run(IProgressMonitor monitor) { ProjectVersion version = model.getObject(); TeamProvider provider = TeamProviderUtil.getTeamProvider(version.getParent() .getTeamProvider()); CDOTransaction transaction = Activator.getDefault() .getRepositoryConnector() .openTransaction(); try { version = transaction.getObject(version); SubMonitor subMonitor = SubMonitor.convert(monitor, "Committing", 100); provider.commit(version, subMonitor.newChild(100)); } catch (TeamProviderException e) { logger.error("Commit failed", e); return new Status(IStatus.ERROR, Activator.BUNDLE_ID, "Commit Failed", e); } finally { transaction.close(); } return Status.OK_STATUS; } }; return new ProgressShowingAjaxButton("commit", progressPanel, runnable, nls("commit.version.job.label",getModelObject().getName())) { private static final long serialVersionUID = 1L; public boolean isVisible() { ProjectVersion version = model.getObject(); TeamProvider provider = TeamProviderUtil.getTeamProvider(version.getParent() .getTeamProvider()); if (provider == null) return false; File file = new File(version.absoluteFilePath().toFileString()); return (file.isDirectory()); }; }; } private Component createCheckoutAction(ProgressPanel progressPanel, final IModel<ProjectVersion> model) { RunnableWithProgress runnable = new RunnableWithProgress() { private static final long serialVersionUID = 1L; @Override public IStatus run(IProgressMonitor monitor) { CDOTransaction transaction = Activator.getDefault().getRepositoryConnector().openTransaction(); try { SubMonitor subMonitor = SubMonitor.convert(monitor,100); ProjectVersion version = model.getObject(); version = transaction.getObject(version); TeamProvider provider = TeamProviderUtil.getTeamProvider(version.getParent().getTeamProvider()); provider.checkout(version, subMonitor.newChild(75)); rescanProject(subMonitor.newChild(25), model); } catch (TeamProviderException e) { logger.error("Checkout failed",e); return new Status(IStatus.ERROR, Activator.BUNDLE_ID, "Checkout failed",e); } catch (CommitException e) { return new Status(IStatus.ERROR, Activator.BUNDLE_ID, "Transaction commit failed",e); } finally{ try { transaction.commit(); } catch (CommitException e) { logger.error("Failed to commit the transaction",e); return new Status(IStatus.ERROR, Activator.BUNDLE_ID, "Failed to commit the transaction",e); } transaction.close(); } return Status.OK_STATUS; } }; return new ProgressShowingAjaxButton("checkout", progressPanel, runnable, nls("checkout.version.job.label",getModelObject().getName())) { private static final long serialVersionUID = 1L; public boolean isVisible() { ProjectVersion version = model.getObject(); TeamProvider provider = TeamProviderUtil.getTeamProvider(version.getParent().getTeamProvider()); if (provider == null) return false; File file = new File(version.absoluteFilePath().toFileString()); return (!file.isDirectory()); }; }; } private Component createRescanAction(ProgressPanel progressPanel, final IModel<ProjectVersion> model) { RunnableWithProgress runnable = new RunnableWithProgress() { private static final long serialVersionUID = 1L; @Override public IStatus run(IProgressMonitor monitor) { try { rescanProject(monitor, model); } catch (CommitException e) { return new Status(IStatus.ERROR, Activator.BUNDLE_ID, "Transaction commit failed",e); } return Status.OK_STATUS; } }; return new ProgressShowingAjaxButton("rescan", progressPanel, runnable, nls("rescan.version.job.label",getModelObject().getName())) { private static final long serialVersionUID = 1L; public boolean isVisible() { // ProjectVersion version = model.getObject(); // File file = new // File(version.absoluteFilePath().toFileString()); // return (file.isDirectory()); return true; }; }; } private void rescanProject(IProgressMonitor monitor, final IModel<ProjectVersion> model) throws CommitException { ScanConfiguration scanConfiguration = PreferencesUtil.getScanConfigForProject(getModelObject()); ProjectVersion version = model.getObject(); SubMonitor subMonitor = SubMonitor.convert(monitor, "Scanning", 100); CDOTransaction transaction = Activator.getDefault().getRepositoryConnector().openTransaction(); version = transaction.getObject(version); version.fullScan(scanConfiguration, subMonitor.newChild(50)); subMonitor.setTaskName("Database Sync"); try { transaction.commit(subMonitor.newChild(50)); } finally { transaction.close(); PropertyPersistenceService persistenceService = Activator.getDefault().getPersistenceService(); if(persistenceService!=null) persistenceService.clearCache(); else logger.error("Could not obtain property persistence service"); } monitor.done(); } public static class VersionsConfig extends AbstractConfigSection<Project> { private static final long serialVersionUID = 1L; @Override public WebMarkupContainer doCreateContents(String id, IModel<Project> input, Preferences prefs) { return new ProjectVersionsConfigSection(id, input, prefs); } @Override public void commit(IModel<Project> input, Preferences config) { // TODO Auto-generated method stub } @Override public String getRequiredPermission() { String projectName = null; if(getDomainObject()!=null) projectName = getDomainObject().getName(); return CommonPermissions.constructPermission(CommonPermissions.PROJECT,projectName,CommonPermissions.ACTION_CONFIG); } } static class DeleteAction extends IndicatingAjaxButton { private IModel<ProjectVersion> model; private IModel<String> confirmationText; private static final long serialVersionUID = 1L; public DeleteAction(String id, IModel<ProjectVersion> model, IModel<String> confirmationText) { super(id); this.model = model; this.confirmationText = confirmationText; } @Override protected void onAfterSubmit(AjaxRequestTarget target, Form<?> form) { ProjectVersion projectVersion = model.getObject(); CDOTransaction transaction = Activator.getDefault().getRepositoryConnector().openTransaction(); projectVersion = transaction.getObject(projectVersion); Preferences preferences = PreferencesUtil.scopeFor(projectVersion); try { PreferencesUtil.deleteNode(preferences); File directory = new File(projectVersion.absolutPath().toFileString()); FileUtil.delete(directory); projectVersion.getParent().getChildren().remove(projectVersion); transaction.commit(); setResponsePage(SettingsPage.class, getPage().getPageParameters()); } catch (CommitException e) { logger.error("Commit failed",e); getSession().error(e.getMessage()); } catch (BackingStoreException e) { logger.error("Failed to delete project preferences",e); getSession().error(e.getMessage()); } finally { transaction.close(); } } @Override protected void updateAjaxAttributes( AjaxRequestAttributes attributes ) { super.updateAjaxAttributes( attributes ); AjaxCallListener ajaxCallListener = new AjaxCallListener(); ajaxCallListener.onPrecondition( "return confirm('" + confirmationText.getObject() + "');" ); attributes.getAjaxCallListeners().add( ajaxCallListener ); } } }