blob: 7105d15f4575b8d8dcbea81c44cd1a4cddcf879e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2005 IBM Corporation 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.ide;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IBundleGroup;
import org.eclipse.core.runtime.IBundleGroupProvider;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.PluginVersionIdentifier;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.application.IWorkbenchConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchAdvisor;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.internal.ide.model.WorkbenchAdapterBuilder;
import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
import org.eclipse.ui.progress.IProgressService;
import org.eclipse.update.core.SiteManager;
import org.osgi.framework.Bundle;
/**
* IDE-specified workbench advisor which configures the workbench for use as
* an IDE.
* <p>
* Note: This class replaces <code>org.eclipse.ui.internal.Workbench</code>.
* </p>
*
* @since 3.0
*/
public class IDEWorkbenchAdvisor extends WorkbenchAdvisor {
private static final String WORKBENCH_PREFERENCE_CATEGORY_ID = "org.eclipse.ui.preferencePages.Workbench"; //$NON-NLS-1$
/**
* The dialog setting key to access the known installed features
* since the last time the workbench was run.
*/
private static final String INSTALLED_FEATURES = "installedFeatures"; //$NON-NLS-1$
private static IDEWorkbenchAdvisor workbenchAdvisor = null;
/**
* Event loop exception handler for the advisor.
*/
private IDEExceptionHandler exceptionHandler = null;
/**
* Contains the workspace location if the -showlocation command line
* argument is specified, or <code>null</code> if not specified.
*/
private String workspaceLocation = null;
/**
* Ordered map of versioned feature ids -> info that are new for this
* session; <code>null</code> if uninitialized. Key type:
* <code>String</code>, Value type: <code>AboutInfo</code>.
*/
private Map newlyAddedBundleGroups;
/**
* Array of <code>AboutInfo</code> for all new installed
* features that specify a welcome perspective.
*/
private AboutInfo[] welcomePerspectiveInfos = null;
/**
* Helper for managing activites in response to workspace changes.
*/
private IDEWorkbenchActivityHelper activityHelper = null;
/**
* Helper for managing work that is performed when the system is
* otherwise idle.
*/
private IDEIdleHelper idleHelper;
/**
* Creates a new workbench advisor instance.
*/
public IDEWorkbenchAdvisor() {
super();
if (workbenchAdvisor != null) {
throw new IllegalStateException();
}
workbenchAdvisor = this;
}
/* (non-Javadoc)
* @see org.eclipse.ui.application.WorkbenchAdvisor#initialize
*/
public void initialize(IWorkbenchConfigurer configurer) {
// make sure we always save and restore workspace state
configurer.setSaveAndRestore(true);
// setup the event loop exception handler
exceptionHandler = new IDEExceptionHandler(configurer);
// register workspace adapters
WorkbenchAdapterBuilder.registerAdapters();
// get the command line arguments
String[] cmdLineArgs = Platform.getCommandLineArgs();
// include the workspace location in the title
// if the command line option -showlocation is specified
for (int i = 0; i < cmdLineArgs.length; i++) {
if ("-showlocation".equalsIgnoreCase(cmdLineArgs[i])) { //$NON-NLS-1$
String name = null;
if (cmdLineArgs.length > i + 1)
name = cmdLineArgs[i+1];
if (name != null && name.indexOf("-") == -1) //$NON-NLS-1$
workspaceLocation = name;
else
workspaceLocation = Platform.getLocation().toOSString();
break;
}
}
// register shared images
declareWorkbenchImages();
// initialize the activity helper
activityHelper = IDEWorkbenchActivityHelper.getInstance();
//initialize idle handler
idleHelper = new IDEIdleHelper(configurer);
}
/* (non-Javadoc)
* @see org.eclipse.ui.application.WorkbenchAdvisor#preStartup()
*/
public void preStartup() {
//Suspend background jobs while we startup
Platform.getJobManager().suspend();
//Register the build actions
IProgressService service = PlatformUI.getWorkbench()
.getProgressService();
ImageDescriptor newImage = IDEInternalWorkbenchImages
.getImageDescriptor(IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC);
service.registerIconForFamily(newImage,
ResourcesPlugin.FAMILY_MANUAL_BUILD);
service.registerIconForFamily(newImage,
ResourcesPlugin.FAMILY_AUTO_BUILD);
}
/* (non-Javadoc)
* @see org.eclipse.ui.application.WorkbenchAdvisor#postStartup()
*/
public void postStartup() {
try {
refreshFromLocal();
checkUpdates();
} finally {//Resume background jobs after we startup
Platform.getJobManager().resume();
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.application.WorkbenchAdvisor#postShutdown
*/
public void postShutdown() {
if (activityHelper != null) {
activityHelper.shutdown();
activityHelper = null;
}
if (idleHelper != null) {
idleHelper.shutdown();
idleHelper = null;
}
if (IDEWorkbenchPlugin.getPluginWorkspace() != null) {
disconnectFromWorkspace();
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.application.WorkbenchAdvisor#eventLoopException
*/
public void eventLoopException(Throwable exception) {
super.eventLoopException(exception);
if (exceptionHandler != null) {
exceptionHandler.handleException(exception);
} else {
if (getWorkbenchConfigurer() != null) {
getWorkbenchConfigurer().emergencyClose();
}
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.application.WorkbenchAdvisor#createWorkbenchWindowAdvisor(org.eclipse.ui.application.IWorkbenchWindowConfigurer)
*/
public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
return new IDEWorkbenchWindowAdvisor(this, configurer);
}
/**
* Return true if the intro plugin is present and false otherwise.
*/
public boolean hasIntro() {
return getWorkbenchConfigurer().getWorkbench().getIntroManager()
.hasIntro();
}
private void refreshFromLocal() {
String[] commandLineArgs = Platform.getCommandLineArgs();
IPreferenceStore store = IDEWorkbenchPlugin.getDefault()
.getPreferenceStore();
boolean refresh = store
.getBoolean(IDEInternalPreferences.REFRESH_WORKSPACE_ON_STARTUP);
if (!refresh)
return;
//Do not refresh if it was already done by core on startup.
for (int i = 0; i < commandLineArgs.length; i++)
if (commandLineArgs[i].equalsIgnoreCase("-refresh")) //$NON-NLS-1$
return;
final IContainer root = ResourcesPlugin.getWorkspace().getRoot();
Job job = new WorkspaceJob(IDEWorkbenchMessages.Workspace_refreshing) {
public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
root.refreshLocal(IResource.DEPTH_INFINITE, monitor);
return Status.OK_STATUS;
}
};
job.setRule(root);
job.schedule();
}
/**
* Disconnect from the core workspace.
*/
private void disconnectFromWorkspace() {
// save the workspace
final MultiStatus status = new MultiStatus(
IDEWorkbenchPlugin.IDE_WORKBENCH, 1, IDEWorkbenchMessages.ProblemSavingWorkbench, null);
IRunnableWithProgress runnable = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) {
try {
status.merge(ResourcesPlugin.getWorkspace().save(true,
monitor));
} catch (CoreException e) {
status.merge(e.getStatus());
}
}
};
try {
new ProgressMonitorJobsDialog(null).run(true, false, runnable);
} catch (InvocationTargetException e) {
status
.merge(new Status(
IStatus.ERROR,
IDEWorkbenchPlugin.IDE_WORKBENCH,
1,
IDEWorkbenchMessages.InternalError, e.getTargetException()));
} catch (InterruptedException e) {
status.merge(new Status(IStatus.ERROR,
IDEWorkbenchPlugin.IDE_WORKBENCH, 1, IDEWorkbenchMessages.InternalError, e));
}
ErrorDialog.openError(null, IDEWorkbenchMessages.ProblemsSavingWorkspace,
null, status, IStatus.ERROR | IStatus.WARNING);
if (!status.isOK()) {
IDEWorkbenchPlugin.log(IDEWorkbenchMessages.ProblemsSavingWorkspace, status);
}
}
/**
* Checks if the -newUpdates command line argument is present
* and if so, opens the update manager.
*/
private void checkUpdates() {
boolean newUpdates = false;
String[] commandLineArgs = Platform.getCommandLineArgs();
for (int i = 0; i < commandLineArgs.length; i++) {
if (commandLineArgs[i].equalsIgnoreCase("-newUpdates")) { //$NON-NLS-1$
newUpdates = true;
break;
}
}
if (newUpdates) {
try {
SiteManager.handleNewChanges();
} catch (CoreException e) {
IDEWorkbenchPlugin.log(
"Problem opening update manager", e.getStatus()); //$NON-NLS-1$
}
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.application.WorkbenchAdvisor#getDefaultPageInput
*/
public IAdaptable getDefaultPageInput() {
return ResourcesPlugin.getWorkspace().getRoot();
}
/* (non-Javadoc)
* @see org.eclipse.ui.application.WorkbenchAdvisor
*/
public String getInitialWindowPerspectiveId() {
int index = PlatformUI.getWorkbench().getWorkbenchWindowCount() - 1;
String perspectiveId = null;
AboutInfo[] welcomeInfos = getWelcomePerspectiveInfos();
if (index >= 0 && welcomeInfos != null
&& index < welcomeInfos.length) {
perspectiveId = welcomeInfos[index].getWelcomePerspectiveId();
}
if (perspectiveId == null) {
perspectiveId = IDE.RESOURCE_PERSPECTIVE_ID;
}
return perspectiveId;
}
/**
* Returns the map of versioned feature ids -> info object for all installed
* features. The format of the versioned feature id (the key of the map) is
* featureId + ":" + versionId.
*
* @return map of versioned feature ids -> info object (key type:
* <code>String</code>, value type: <code>AboutInfo</code>)
* @since 3.0
*/
private Map computeBundleGroupMap() {
// use tree map to get predicable order
Map ids = new TreeMap();
IBundleGroupProvider[] providers = Platform.getBundleGroupProviders();
for (int i = 0; i < providers.length; ++i) {
IBundleGroup[] groups = providers[i].getBundleGroups();
for (int j = 0; j < groups.length; ++j) {
IBundleGroup group = groups[j];
AboutInfo info = new AboutInfo(group);
String version = info.getVersionId();
version = version == null ? "0.0.0" //$NON-NLS-1$
: new PluginVersionIdentifier(version).toString();
String versionedFeature = group.getIdentifier() + ":" + version; //$NON-NLS-1$
ids.put(versionedFeature, info);
}
}
return ids;
}
/**
* Returns the ordered map of versioned feature ids -> AboutInfo that are
* new for this session.
*
* @return ordered map of versioned feature ids (key type:
* <code>String</code>) -> infos (value type:
* <code>AboutInfo</code>).
*/
public Map getNewlyAddedBundleGroups() {
if (newlyAddedBundleGroups == null)
newlyAddedBundleGroups = createNewBundleGroupsMap();
return newlyAddedBundleGroups;
}
/**
* Updates the old features setting and returns a map of new features.
*/
private Map createNewBundleGroupsMap() {
// retrieve list of installed bundle groups from last session
IDialogSettings settings = IDEWorkbenchPlugin.getDefault()
.getDialogSettings();
String[] previousFeaturesArray = settings.getArray(INSTALLED_FEATURES);
// get a map of currently installed bundle groups and store it for next session
Map bundleGroups = computeBundleGroupMap();
String[] currentFeaturesArray = new String[bundleGroups.size()];
bundleGroups.keySet().toArray(currentFeaturesArray);
settings.put(INSTALLED_FEATURES, currentFeaturesArray);
// remove the previously known from the current set
if (previousFeaturesArray != null)
for (int i = 0; i < previousFeaturesArray.length; ++i)
bundleGroups.remove(previousFeaturesArray[i]);
return bundleGroups;
}
/**
* Declares all IDE-specific workbench images. This includes both "shared"
* images (named in {@link IDE.SharedImages}) and
* internal images (named in
* {@link org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages}).
*
* @see IWorkbenchConfigurer#declareImage
*/
private void declareWorkbenchImages() {
final String ICONS_PATH = "$nl$/icons/full/";//$NON-NLS-1$
final String PATH_ELOCALTOOL = ICONS_PATH + "elcl16/"; //Enabled toolbar icons.//$NON-NLS-1$
final String PATH_ETOOL = ICONS_PATH + "etool16/"; //Enabled toolbar icons.//$NON-NLS-1$
final String PATH_DTOOL = ICONS_PATH + "dtool16/"; //Disabled toolbar icons.//$NON-NLS-1$
final String PATH_OBJECT = ICONS_PATH + "obj16/"; //Model object icons//$NON-NLS-1$
final String PATH_WIZBAN = ICONS_PATH + "wizban/"; //Wizard icons//$NON-NLS-1$
Bundle ideBundle = Platform.getBundle(IDEWorkbenchPlugin.IDE_WORKBENCH);
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC, PATH_ETOOL
+ "build_exec.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_HOVER,
PATH_ETOOL + "build_exec.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_DISABLED,
PATH_DTOOL + "build_exec.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC, PATH_ETOOL
+ "search_src.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_HOVER,
PATH_ETOOL + "search_src.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_DISABLED,
PATH_DTOOL + "search_src.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_ETOOL_NEXT_NAV, PATH_ETOOL
+ "next_nav.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_ETOOL_PREVIOUS_NAV, PATH_ETOOL
+ "prev_nav.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_WIZBAN_NEWPRJ_WIZ, PATH_WIZBAN
+ "newprj_wiz.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFOLDER_WIZ,
PATH_WIZBAN + "newfolder_wiz.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFILE_WIZ, PATH_WIZBAN
+ "newfile_wiz.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTDIR_WIZ,
PATH_WIZBAN + "importdir_wiz.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTZIP_WIZ,
PATH_WIZBAN + "importzip_wiz.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTDIR_WIZ,
PATH_WIZBAN + "exportdir_wiz.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTZIP_WIZ,
PATH_WIZBAN + "exportzip_wiz.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_WIZBAN_RESOURCEWORKINGSET_WIZ,
PATH_WIZBAN + "workset_wiz.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_DLGBAN_SAVEAS_DLG,
PATH_WIZBAN + "saveas_wiz.gif", false); //$NON-NLS-1$
declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJ_PROJECT,
PATH_OBJECT + "prj_obj.gif", true); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDE.SharedImages.IMG_OBJ_PROJECT_CLOSED, PATH_OBJECT
+ "cprj_obj.gif", true); //$NON-NLS-1$
declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OPEN_MARKER,
PATH_ELOCALTOOL + "gotoobj_tsk.gif", true); //$NON-NLS-1$
// task objects
//declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_HPRIO_TSK, PATH_OBJECT+"hprio_tsk.gif");
//declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_MPRIO_TSK, PATH_OBJECT+"mprio_tsk.gif");
//declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LPRIO_TSK, PATH_OBJECT+"lprio_tsk.gif");
declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_TASK_TSK,
PATH_OBJECT + "taskmrk_tsk.gif", true); //$NON-NLS-1$
declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_BKMRK_TSK,
PATH_OBJECT + "bkmrk_tsk.gif", true); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_OBJS_COMPLETE_TSK, PATH_OBJECT
+ "complete_tsk.gif", true); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_OBJS_INCOMPLETE_TSK, PATH_OBJECT
+ "incomplete_tsk.gif", true); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_ITEM, PATH_OBJECT
+ "welcome_item.gif", true); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_BANNER, PATH_OBJECT
+ "welcome_banner.gif", true); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_LCL_FLAT_LAYOUT, PATH_ELOCALTOOL
+ "flatLayout.gif", true); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_LCL_HIERARCHICAL_LAYOUT, PATH_ELOCALTOOL
+ "hierarchicalLayout.gif", true); //$NON-NLS-1$
declareWorkbenchImage(ideBundle,
IDEInternalWorkbenchImages.IMG_ETOOL_PROBLEM_CATEGORY, PATH_ETOOL
+ "problem_category.gif", true); //$NON-NLS-1$
// synchronization indicator objects
//declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_WBET_STAT, PATH_OVERLAY+"wbet_stat.gif");
//declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_SBET_STAT, PATH_OVERLAY+"sbet_stat.gif");
//declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_CONFLICT_STAT, PATH_OVERLAY+"conflict_stat.gif");
// content locality indicator objects
//declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_NOTLOCAL_STAT, PATH_STAT+"notlocal_stat.gif");
//declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LOCAL_STAT, PATH_STAT+"local_stat.gif");
//declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_FILLLOCAL_STAT, PATH_STAT+"filllocal_stat.gif");
}
/**
* Declares an IDE-specific workbench image.
*
* @param symbolicName the symbolic name of the image
* @param path the path of the image file; this path is relative to the base
* of the IDE plug-in
* @param shared <code>true</code> if this is a shared image, and
* <code>false</code> if this is not a shared image
* @see IWorkbenchConfigurer#declareImage
*/
private void declareWorkbenchImage(Bundle ideBundle, String symbolicName,
String path, boolean shared) {
URL url = Platform.find(ideBundle, new Path(path));
ImageDescriptor desc = ImageDescriptor.createFromURL(url);
getWorkbenchConfigurer().declareImage(symbolicName, desc, shared);
}
/* (non-Javadoc)
* @see org.eclipse.ui.application.WorkbenchAdvisor#getMainPreferencePageId
*/
public String getMainPreferencePageId() {
// indicate that we want the Workench preference page to be prominent
return WORKBENCH_PREFERENCE_CATEGORY_ID;
}
/**
* @return the workspace location string, or <code>null</code> if
* the location is not being shown
*/
public String getWorkspaceLocation() {
return workspaceLocation;
}
/**
* @return the welcome perspective infos, or <code>null</code> if none
* or if they should be ignored due to the new intro being present
*/
public AboutInfo[] getWelcomePerspectiveInfos() {
if (welcomePerspectiveInfos == null) {
// support old welcome perspectives if intro plugin is not present
if (!hasIntro()) {
Map m = getNewlyAddedBundleGroups();
ArrayList list = new ArrayList(m.size());
for (Iterator i = m.values().iterator(); i.hasNext();) {
AboutInfo info = (AboutInfo) i.next();
if (info != null && info.getWelcomePerspectiveId() != null
&& info.getWelcomePageURL() != null)
list.add(info);
}
welcomePerspectiveInfos = new AboutInfo[list.size()];
list.toArray(welcomePerspectiveInfos);
}
}
return welcomePerspectiveInfos;
}
}