Skip to main content
summaryrefslogtreecommitdiffstats
blob: 9f4ac41c33704b3f048f675b6be4fa813f9f7194 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*******************************************************************************
 *  Copyright (c) 2010  Oracle. 
 *  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: 
 *  	Oracle - initial API and implementation
 *******************************************************************************/
package org.eclipse.jpt.eclipselink.core.internal.utility;

import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.util.IClassFileReader;
import org.eclipse.jdt.core.util.IFieldInfo;
import org.eclipse.jpt.core.internal.utility.KeyClassesValidator;
import org.eclipse.jpt.eclipselink.core.internal.JptEclipseLinkCoreMessages;
import org.eclipse.jpt.eclipselink.core.internal.JptEclipseLinkCorePlugin;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jst.common.project.facet.core.libprov.user.UserLibraryProviderInstallOperationConfig;
import org.eclipse.jst.common.project.facet.core.libprov.user.UserLibraryValidator;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.osgi.framework.Version;

/**
 * Library validator for EclipseLink user libraries.
 * 
 * This has two facets:
 * 	- eclipselink version:  In order to validate that the correct eclipselink.jar is present in the 
 * 		user library, the extension using this should specify none or more version ranges using a 
 * 		standard library provider param expression, but with the prefix "version-range".  The actual
 * 		version of the eclipselink build will be checked against the union of these version ranges.
 * 		(e.g. <param name="validator.param.0" value="version-range:[2.0, 3.0)"/> )
 * - jpa key classes:  In order to validate that the correct jpa.jar is present in the user 
 * 		library (since version of that jar is impossible to check,) the extension using this should 
 * 		specify none or more key classes using a standard library provider param expression, but
 * 		with the prefix "key-class".  The user library will check that all specified key classes
 * 		are present.
 * 		(e.g. <param name="validator.param.1" value="key-class:javax.persistence.Entity"/> )
 */
public class EclipseLinkLibraryValidator
	extends UserLibraryValidator
{
	private final static String VERSION_CLASS_PATH = "org/eclipse/persistence/Version.class";
	
	private final static String VERSION_FIELD_NAME = "version";
	
	private final static String VERSION_RANGE_PREFIX = "version-range:";
	
	private final static String KEY_CLASS_PREFIX = "key-class:";
	
	private final List<VersionRange> versionRanges = new ArrayList<VersionRange>();
	
	private final List<String> keyClasses = new ArrayList<String>();
	
	
	private final KeyClassesValidator keyClassesValidator = new KeyClassesValidator();
	
	
	public EclipseLinkLibraryValidator() {
		super();
	}
	
	
	@Override
    public void init(final List<String> params) {
		for (String param : params) {
			if (param.startsWith(VERSION_RANGE_PREFIX)) {
				versionRanges.add(new VersionRange(param.replaceFirst(VERSION_RANGE_PREFIX, "")));
			}
			else if (param.startsWith(KEY_CLASS_PREFIX)) {
				keyClasses.add(param.replaceFirst(KEY_CLASS_PREFIX, ""));
			}
		}
		this.keyClassesValidator.init(this.keyClasses);
	}
	
	@Override
	public IStatus validate(UserLibraryProviderInstallOperationConfig config) {
		if (! this.keyClassesValidator.validate(config).isOK()) {
			return new Status(
					IStatus.ERROR, JptEclipseLinkCorePlugin.PLUGIN_ID,
					JptEclipseLinkCoreMessages.EclipseLinkLibraryValidator_invalidJpaLibrary);
		}
		
		Version version = null;
		for (IClasspathEntry cpe : config.resolve()) {
			String versionString = null;
			if (cpe.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
				IClassFileReader classReader = 
						ToolFactory.createDefaultClassFileReader(
							cpe.getPath().toFile().getAbsolutePath(), VERSION_CLASS_PATH, IClassFileReader.FIELD_INFOS);
				if (classReader != null) {
					for (IFieldInfo field : classReader.getFieldInfos()) {
						if (StringTools.stringsAreEqual(field.getName(), VERSION_FIELD_NAME.toCharArray())) {
							try {
								versionString = field.getConstantValueAttribute().getConstantValue().getStringValue();
							}
							catch (Exception e) {
								// potentially a bit could go wrong with that last line, but if any
								// assumptions aren't met, there's no value
							}
							break;
						}
					}
				}
				if (versionString != null) {
					if (version != null) {
						return new Status(
								IStatus.ERROR, JptEclipseLinkCorePlugin.PLUGIN_ID,
								JptEclipseLinkCoreMessages.EclipseLinkLibraryValidator_multipleEclipseLinkVersions);
					}
					else {
						version = new Version(versionString);
					}
				}
			}
		}
		
		if (version == null) {
			return new Status(
					IStatus.ERROR, JptEclipseLinkCorePlugin.PLUGIN_ID, 
					JptEclipseLinkCoreMessages.EclipseLinkLibraryValidator_noEclipseLinkVersion);
		}
		
		for (VersionRange versionRange : this.versionRanges) {
			if (! versionRange.isIncluded(version)) {
				return new Status(
						IStatus.ERROR, JptEclipseLinkCorePlugin.PLUGIN_ID, 
						JptEclipseLinkCoreMessages.EclipseLinkLibraryValidator_improperEclipseLinkVersion);
			}
		}
		
		return Status.OK_STATUS;
	}
}

Back to the top