1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.workbench.internal;
\r
14 import java.lang.reflect.InvocationTargetException;
\r
15 import java.net.InetSocketAddress;
\r
16 import java.util.HashSet;
\r
17 import java.util.Set;
\r
19 import org.eclipse.core.runtime.IProgressMonitor;
\r
20 import org.eclipse.core.runtime.IStatus;
\r
21 import org.eclipse.core.runtime.MultiStatus;
\r
22 import org.eclipse.core.runtime.Status;
\r
23 import org.eclipse.jface.action.IAction;
\r
24 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
\r
25 import org.eclipse.jface.operation.IRunnableWithProgress;
\r
26 import org.eclipse.swt.widgets.Display;
\r
27 import org.eclipse.ui.IWorkbenchWindow;
\r
28 import org.simantics.application.arguments.ApplicationUtils;
\r
29 import org.simantics.application.arguments.IArguments;
\r
30 import org.simantics.application.arguments.SimanticsArguments;
\r
31 import org.simantics.db.ReadGraph;
\r
32 import org.simantics.db.Resource;
\r
33 import org.simantics.db.Session;
\r
34 import org.simantics.db.common.request.ReadRequest;
\r
35 import org.simantics.db.common.utils.NameUtils;
\r
36 import org.simantics.db.exception.DatabaseException;
\r
37 import org.simantics.db.layer0.util.SimanticsKeys;
\r
38 import org.simantics.db.management.ISessionContext;
\r
39 import org.simantics.db.management.discovery.InetAddressUtils;
\r
40 import org.simantics.db.request.Read;
\r
41 import org.simantics.project.IProject;
\r
42 import org.simantics.project.ProjectKeys;
\r
43 import org.simantics.project.ProjectUtil;
\r
44 import org.simantics.project.exception.ProjectException;
\r
45 import org.simantics.project.utils.GraphPathUtils;
\r
46 import org.simantics.ui.db.SessionData;
\r
47 import org.simantics.ui.db.SessionRestoreUtils;
\r
48 import org.simantics.ui.internal.Activator;
\r
49 import org.simantics.ui.workbench.action.ChooseActionRequest;
\r
50 import org.simantics.utils.ui.ExceptionUtils;
\r
51 import org.simantics.utils.ui.action.IPriorityAction;
\r
52 import org.simantics.utils.ui.dialogs.ShowMessage;
\r
54 public class Initializer implements Runnable {
\r
56 private final IArguments args;
\r
58 // private String defaultPerspectiveId;
\r
61 * This will be !ok if something fatal for startup has happened.
\r
63 private final IStatus status = Status.OK_STATUS;
\r
65 private ISessionContext ctx;
\r
67 private IProject project;
\r
69 private Resource model;
\r
71 private final IWorkbenchWindow window;
\r
73 // private Resource experiment;
\r
76 public Initializer(IArguments args, IWorkbenchWindow window) {
\r
78 this.window = window;
\r
79 // this.defaultPerspectiveId = defaultPerspectiveId;
\r
86 } catch (DatabaseException e) {
\r
87 e.printStackTrace();
\r
88 } catch (ProjectException e) {
\r
89 e.printStackTrace();
\r
93 public IStatus getStatus() {
\r
97 public ISessionContext getSessionContext() {
\r
101 public IProject getProject() {
\r
105 public Resource getModel() {
\r
109 public boolean perform() throws DatabaseException, ProjectException {
\r
110 // Nothing further can be done if no server is specified
\r
111 if (!args.contains(SimanticsArguments.SERVER))
\r
114 // Try to connect to designated server and project.
\r
115 // Use null local server location to indicate checkout
\r
116 String server = args.get(SimanticsArguments.SERVER);
\r
117 if(server.indexOf(':') == -1 && args.contains(SimanticsArguments.PORT)) {
\r
118 server = server+":"+args.get(SimanticsArguments.PORT);
\r
120 InetSocketAddress serverAddress = InetAddressUtils.parseUnresolved(server);
\r
121 String[] projectPath = ApplicationUtils.decodePath(args.get(SimanticsArguments.PROJECT));
\r
122 final SessionData data = new SessionData(null, serverAddress, projectPath);
\r
124 final MultiStatus status = new MultiStatus(Activator.PLUGIN_ID, IStatus.OK, "Database session could not be initialized.", null);
\r
125 // final ProgressMonitorDialog dialog = new ProgressMonitorDialog(null);
\r
127 final ProgressMonitorDialog dialog = new ProgressMonitorDialog(null);
\r
129 dialog.run(false, true, new IRunnableWithProgress() {
\r
131 public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
\r
132 ctx = SessionRestoreUtils.restoreSession(status, monitor, data);
\r
133 //ctx = sessionResult;
\r
136 } catch (InvocationTargetException e) {
\r
137 ExceptionUtils.logAndShowError(e);
\r
138 } catch (InterruptedException e) {
\r
139 ExceptionUtils.logAndShowError(e);
\r
142 //IDiscoveryModel model =
\r
145 // IDiscoveryData[] iData = ProjectPlugin.getWorkspace().getDiscoveryModel().getDataSources();
\r
146 // for(int i = 0; i < iData.length; i++) {
\r
147 // IDiscoveryData d = iData[i];
\r
148 // if(d.getLabel().equals(IWorkspaceConstants.DIRECT_SERVERS_LABEL)) {
\r
149 // ServerInfo serverInfo = new ServerInfo(d.getLabel(), serverAddress);
\r
150 // ServerData serverData = new ServerData(null, serverInfo, null);
\r
151 // IServerData[] iServerData = d.getServers();
\r
153 // IServerData[] newServerData = new IServerData[iServerData.length+1];
\r
156 // for(y = 0; y < iServerData.length; y++) {
\r
157 // newServerData[y] = iServerData[y];
\r
160 // newServerData[y] = serverData;
\r
162 // d.setServers(newServerData);
\r
163 // ProjectPlugin.getWorkspace().getDiscoveryModel().updateDataSource(d);
\r
169 //status = sessionResult.status;
\r
170 //if (!status.isOK()) {
\r
175 // Its okay to start the workbench, it will just be reset as the
\r
176 // connection failed.
\r
180 // FIXME: COMPLETE HACK for simupedia
\r
181 // Add a discovery service to get in touch
\r
183 IDiscoveryModel discoveryModel = ProjectPlugin.getWorkspace().getDiscoveryModel();
\r
184 File discoveryFile = ProjectPlugin.getDefault().getStateLocation().append("simupedia-discovery.txt").toFile();
\r
185 FileWriter fw = null;
\r
187 // Overwrite the file.
\r
188 fw = new FileWriter(discoveryFile, false);
\r
189 String serverLine = String.format("'%s' %s\n", data.getAddress().getHostName(), server);
\r
190 fw.write(serverLine);
\r
191 } catch (IOException e) {
\r
192 e.printStackTrace();
\r
194 FileUtils.uncheckedClose(fw);
\r
197 // Add a non-persistent simupedia discovery
\r
198 DiscoveryData d = new DiscoveryData(IDiscoveryType.REMOTE, "Simupedia", discoveryFile);
\r
199 discoveryModel.addDataSource(d);
\r
200 } catch (MalformedURLException e) {
\r
201 // Should never happen.
\r
202 throw new Error(e);
\r
206 // Initialize project
\r
207 if (args.contains(SimanticsArguments.NEW_PROJECT)) {
\r
208 throw new UnsupportedOperationException();
\r
209 //project = newProject(ctx);
\r
210 } else if (args.contains(SimanticsArguments.PROJECT)) {
\r
211 project = loadProject(ctx, projectPath);
\r
214 // Only proceed with model and experiment loading if a project was
\r
215 // successfully created or loaded.
\r
216 if (project != null) {
\r
217 ctx.setHint(ProjectKeys.KEY_PROJECT, project);
\r
218 ctx.setHint(SimanticsKeys.KEY_PROJECT, project.get());
\r
221 if (args.contains(SimanticsArguments.NEW_MODEL)) {
\r
222 //model = newModel(ctx.getSession(), project);
\r
223 } else if (args.contains(SimanticsArguments.MODEL)) {
\r
224 String[] modelPath = ApplicationUtils.decodePath(args.get(SimanticsArguments.MODEL));
\r
225 model = findModel(ctx.getSession(), project, modelPath);
\r
227 // if (model != null) {
\r
228 // findDiagram(ctx.getSession(), model, project);
\r
231 // TODO: load experiment
\r
232 if (args.contains(SimanticsArguments.EXPERIMENT)) {
\r
233 // String[] experimentPath = decodePath(args.get(ProConfArguments.EXPERIMENT));
\r
240 IProject loadProject(ISessionContext ctx, final String[] projectNamePath) throws DatabaseException, ProjectException {
\r
242 IProject project = ctx.getSession().syncRequest(new Read<IProject>() {
\r
245 public IProject perform(ReadGraph graph) throws DatabaseException {
\r
246 Resource projects = graph.getResource("http://Projects");
\r
247 Resource[] path = GraphPathUtils.toResourcePath(graph, projects, projectNamePath, graph
\r
248 .getBuiltins().ConsistsOf);
\r
249 if (path.length == 0) {
\r
250 IllegalArgumentException e = new IllegalArgumentException("");
\r
251 ShowMessage.showError("Error loading the existing project", e.getMessage());
\r
252 throw new DatabaseException(e);
\r
254 return ProjectUtil.loadProject(graph, path[path.length - 1]);
\r
259 project.activate();
\r
263 // final GraphRequestWithResult<IProject> request = new GraphRequestWithResult<IProject>() {
\r
265 // public IProject performWithResult(Graph g) throws Exception {
\r
268 // ctx.getSession().syncRead(request);
\r
269 // if (request.getException() != null) {
\r
270 // ShowMessage.showError("Error loading the existing project", request.getException().getMessage());
\r
273 // return request.getResult();
\r
276 Resource findModel(final Session session, final IProject project, final String[] modelPath) throws DatabaseException {
\r
278 return session.syncRequest(new Read<Resource>() {
\r
281 public Resource perform(ReadGraph graph) throws DatabaseException {
\r
282 Resource[] path = GraphPathUtils.toResourcePath(graph, project.get(), modelPath, graph
\r
283 .getBuiltins().ConsistsOf);
\r
284 if (path.length == 0) {
\r
285 IllegalArgumentException e = new IllegalArgumentException("");
\r
286 ShowMessage.showError("Error loading the existing project", e.getMessage());
\r
287 throw new DatabaseException(e);
\r
289 else return path[path.length - 1];
\r
294 // final GraphRequestWithResult<Resource> request = new GraphRequestWithResult<Resource>() {
\r
296 // public Resource performWithResult(Graph g) {
\r
297 // Resource[] path = GraphPathUtils.toResourcePath(g, project.getResource(), modelPath,
\r
298 // g.getBuiltins().ConsistsOf);
\r
299 // if (path.length == 0)
\r
300 // throw new IllegalArgumentException("");
\r
301 // return path[path.length - 1];
\r
304 // session.syncRead(request);
\r
305 // if (request.getException() != null) {
\r
306 // ShowMessage.showError("Error loading the existing project", request.getException().getMessage());
\r
309 // return request.getResult();
\r
312 final Set<String> reservedProjectNames = new HashSet<String>();
\r
313 // IProject newProject(final ISessionContext ctx) throws DatabaseException {
\r
314 // // ---------------------------------------------------------------------
\r
315 // // Show the wizard to the user.
\r
316 // final NewProjectModel2 model = ProjectWizardUtil.initializeNewProjectModel2(new NullProgressMonitor(), ctx);
\r
317 // final NewProjectWizard2 wizard = new NewProjectWizard2(ctx.getSession(), model, null);
\r
318 // int ok = new WizardDialog(null, wizard).open();
\r
319 // if (ok != Window.OK) {
\r
320 // // User cancelled the wizard.
\r
324 // final DataContainer<IProject> project = new DataContainer<IProject>();
\r
326 // ctx.getSession().syncRequest(new WriteRequest() {
\r
329 // public void perform(WriteGraph g) {
\r
333 // // TODO: add features
\r
334 // System.out.println("TODO: add features to project");
\r
335 // Collection<IProjectFeatureDescriptor> fds = Collections.emptyList();
\r
336 // Resource res = ProjectUtil.createProject(g, model.projectName, fds);
\r
337 // project.set(ProjectUtil.loadProject(g, res, false));
\r
339 // } catch (Exception e) {
\r
340 // ShowMessage.showError("Error creating new project", e.getMessage());
\r
347 // return project.get();
\r
352 Resource newModel(final Session session, final IProject project) {
\r
353 final ISimulationProjectParticipant sim = project.getSingleParticipant(ISimulationProjectParticipant.class);
\r
357 final Resource[] result = { null };
\r
358 final Semaphore sem = new Semaphore(0);
\r
359 findModelLibrary(session, project.getResource(), new RunnableWithParameter<Resource>() {
\r
361 public void run(Resource modelLibrary) {
\r
362 sim.createModel(modelLibrary,
\r
363 new RunnableWithParameter<Resource>() {
\r
365 public void run(Resource model) {
\r
370 new RunnableWithParameter<Throwable>() {
\r
372 public void run(Throwable e) {
\r
373 ErrorLogger.defaultLogError("New model creation failed, see exception for details.", e);
\r
379 new RunnableWithParameter<Throwable>() {
\r
381 public void run(Throwable e) {
\r
383 ErrorLogger.defaultLogError("New model creation failed, see exception for details.", e);
\r
385 ErrorLogger.defaultLogError("New model creation failed, no model library found.", null);
\r
390 // Wait until the model creation has finished or failed.
\r
393 } catch (InterruptedException e) {
\r
400 void findModelLibrary(Session session,
\r
401 final Resource project,
\r
402 final RunnableWithParameter<Resource> libraryAction,
\r
403 final RunnableWithParameter<Throwable> errorCallback)
\r
405 // TODO: all of this is not that generic, what is someone decices he/she
\r
406 // doesn't want a model library called Models at the root of his/her
\r
409 // If the new model consists of a single diagram, open it.
\r
410 session.asyncRequest(new WriteRequest() {
\r
412 public void perform(WriteGraph g) throws Exception {
\r
413 Resource modelLibrary = null;
\r
415 Builtins b = g.getBuiltins();
\r
416 for (Resource r : g.getObjects2(project, b.ConsistsOf)) {
\r
417 if (g.isInstanceOf2(r, b.ModelLibrary)) {
\r
422 // FIXME: this is definitely project specific, not generic.
\r
423 if (modelLibrary == null) {
\r
424 modelLibrary = InstanceFactory.instantiate(g, b.ModelLibrary);
\r
425 GraphUtils.addRelatedScalarString(g, modelLibrary, b.HasName, "Models");
\r
426 g.claim(project, b.ConsistsOf, modelLibrary);
\r
428 libraryAction.run(modelLibrary);
\r
429 } catch (Exception e) {
\r
430 errorCallback.run(e);
\r
437 // void findDiagram(Session session, final Resource model, final IProject project) {
\r
438 // // If the new model consists of a single diagram, open it.
\r
439 // session.asyncRequest(new ReadRequest() {
\r
441 // public void run(ReadGraph g) throws DatabaseException {
\r
442 // Builtins b = g.getBuiltins();
\r
443 // DiagramResource dr = DiagramResource.getInstance(g);
\r
444 // for (Resource r : g.getObjects(model, b.ConsistsOf)) {
\r
445 // if (g.isInstanceOf(r, dr.Diagram)) {
\r
446 // String defaultPerspective = project.getHint(ProjectKeys.DEFAULT_PERSPECTIVE);
\r
447 // openPreferredEditor(ctx.getSession(), r, defaultPerspective);
\r
455 void openPreferredEditor(Session s, final Resource r, final String defaultPerspective) {
\r
457 s.asyncRequest(new ReadRequest() {
\r
460 public void run(ReadGraph g) throws DatabaseException {
\r
461 final String resourceName = NameUtils.getSafeName(g, r);
\r
462 final IPriorityAction[] actions = ChooseActionRequest.findActions(g, r, defaultPerspective);
\r
463 if (actions == null)
\r
465 Display.getDefault().asyncExec(new Runnable() {
\r
467 public void run() {
\r
468 IAction action = ChooseActionRequest.chooseAction(null, actions, resourceName);
\r
469 if (action == null)
\r