1 package org.apache.maven.project;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.Writer;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.LinkedHashMap;
29 import java.util.LinkedHashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Properties;
33 import java.util.Set;
34 import java.util.Objects;
35
36 import org.apache.maven.RepositoryUtils;
37 import org.apache.maven.artifact.Artifact;
38 import org.apache.maven.artifact.ArtifactUtils;
39 import org.apache.maven.artifact.DependencyResolutionRequiredException;
40
41 import org.apache.maven.artifact.factory.ArtifactFactory;
42 import org.apache.maven.artifact.repository.ArtifactRepository;
43 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
44 import org.apache.maven.model.Build;
45 import org.apache.maven.model.CiManagement;
46 import org.apache.maven.model.Contributor;
47 import org.apache.maven.model.Dependency;
48 import org.apache.maven.model.DependencyManagement;
49 import org.apache.maven.model.Developer;
50 import org.apache.maven.model.DistributionManagement;
51 import org.apache.maven.model.Extension;
52 import org.apache.maven.model.IssueManagement;
53 import org.apache.maven.model.License;
54 import org.apache.maven.model.MailingList;
55 import org.apache.maven.model.Model;
56 import org.apache.maven.model.Organization;
57 import org.apache.maven.model.Plugin;
58 import org.apache.maven.model.PluginExecution;
59 import org.apache.maven.model.PluginManagement;
60 import org.apache.maven.model.Prerequisites;
61 import org.apache.maven.model.Profile;
62 import org.apache.maven.model.ReportPlugin;
63 import org.apache.maven.model.ReportSet;
64 import org.apache.maven.model.Reporting;
65 import org.apache.maven.model.Repository;
66 import org.apache.maven.model.Resource;
67 import org.apache.maven.model.Scm;
68 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
69 import org.apache.maven.project.artifact.InvalidDependencyVersionException;
70 import org.apache.maven.project.artifact.MavenMetadataSource;
71 import org.codehaus.plexus.classworlds.realm.ClassRealm;
72 import org.codehaus.plexus.util.xml.Xpp3Dom;
73 import org.eclipse.aether.graph.DependencyFilter;
74 import org.eclipse.aether.repository.RemoteRepository;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 public class MavenProject
93 implements Cloneable
94 {
95
96 private static final Logger LOGGER = LoggerFactory.getLogger( MavenProject.class );
97
98 public static final String EMPTY_PROJECT_GROUP_ID = "unknown";
99
100 public static final String EMPTY_PROJECT_ARTIFACT_ID = "empty-project";
101
102 public static final String EMPTY_PROJECT_VERSION = "0";
103
104 private Model model;
105
106 private MavenProject parent;
107
108 private File file;
109
110 private File basedir;
111
112 private Set<Artifact> resolvedArtifacts;
113
114 private ArtifactFilter artifactFilter;
115
116 private Set<Artifact> artifacts;
117
118 private Artifact parentArtifact;
119
120 private Set<Artifact> pluginArtifacts;
121
122 private List<ArtifactRepository> remoteArtifactRepositories;
123
124 private List<ArtifactRepository> pluginArtifactRepositories;
125
126 private List<RemoteRepository> remoteProjectRepositories;
127
128 private List<RemoteRepository> remotePluginRepositories;
129
130 private List<Artifact> attachedArtifacts = new ArrayList<>();
131
132 private MavenProject executionProject;
133
134 private List<MavenProject> collectedProjects;
135
136 private List<String> compileSourceRoots = new ArrayList<>();
137
138 private List<String> testCompileSourceRoots = new ArrayList<>();
139
140 private List<String> scriptSourceRoots = new ArrayList<>();
141
142 private ArtifactRepository releaseArtifactRepository;
143
144 private ArtifactRepository snapshotArtifactRepository;
145
146 private List<Profile> activeProfiles = new ArrayList<>();
147
148 private Map<String, List<String>> injectedProfileIds = new LinkedHashMap<>();
149
150 private Set<Artifact> dependencyArtifacts;
151
152 private Artifact artifact;
153
154
155 private Map<String, Artifact> artifactMap;
156
157 private Model originalModel;
158
159 private Map<String, Artifact> pluginArtifactMap;
160
161 private Set<Artifact> reportArtifacts;
162
163 private Map<String, Artifact> reportArtifactMap;
164
165 private Set<Artifact> extensionArtifacts;
166
167 private Map<String, Artifact> extensionArtifactMap;
168
169 private Map<String, Artifact> managedVersionMap;
170
171 private Map<String, MavenProject> projectReferences = new HashMap<>();
172
173 private boolean executionRoot;
174
175 private File parentFile;
176
177 private Map<String, Object> context;
178
179 private ClassRealm classRealm;
180
181 private DependencyFilter extensionDependencyFilter;
182
183 private final Set<String> lifecyclePhases = Collections.synchronizedSet( new LinkedHashSet<String>() );
184
185 public MavenProject()
186 {
187 Model model = new Model();
188
189 model.setGroupId( EMPTY_PROJECT_GROUP_ID );
190 model.setArtifactId( EMPTY_PROJECT_ARTIFACT_ID );
191 model.setVersion( EMPTY_PROJECT_VERSION );
192
193 setModel( model );
194 }
195
196 public MavenProject( Model model )
197 {
198 setModel( model );
199 }
200
201 public MavenProject( MavenProject project )
202 {
203 deepCopy( project );
204 }
205
206 public File getParentFile()
207 {
208 return parentFile;
209 }
210
211 public void setParentFile( File parentFile )
212 {
213 this.parentFile = parentFile;
214 }
215
216
217
218
219
220 public Artifact getArtifact()
221 {
222 return artifact;
223 }
224
225 public void setArtifact( Artifact artifact )
226 {
227 this.artifact = artifact;
228 }
229
230
231 public Model getModel()
232 {
233 return model;
234 }
235
236
237
238
239
240
241 public MavenProject getParent()
242 {
243 return parent;
244 }
245
246 public void setParent( MavenProject parent )
247 {
248 this.parent = parent;
249 }
250
251 public boolean hasParent()
252 {
253 return getParent() != null;
254 }
255
256 public File getFile()
257 {
258 return file;
259 }
260
261 public void setFile( File file )
262 {
263 this.file = file;
264 this.basedir = file != null ? file.getParentFile() : null;
265 }
266
267
268
269
270
271
272 public void setPomFile( File file )
273 {
274 this.file = file;
275 }
276
277 public File getBasedir()
278 {
279 return basedir;
280 }
281
282 public void setDependencies( List<Dependency> dependencies )
283 {
284 getModel().setDependencies( dependencies );
285 }
286
287 public List<Dependency> getDependencies()
288 {
289 return getModel().getDependencies();
290 }
291
292 public DependencyManagement getDependencyManagement()
293 {
294 return getModel().getDependencyManagement();
295 }
296
297
298
299
300
301 private void addPath( List<String> paths, String path )
302 {
303 if ( path != null )
304 {
305 path = path.trim();
306 if ( path.length() > 0 )
307 {
308 File file = new File( path );
309 if ( file.isAbsolute() )
310 {
311 path = file.getAbsolutePath();
312 }
313 else if ( ".".equals( path ) )
314 {
315 path = getBasedir().getAbsolutePath();
316 }
317 else
318 {
319 path = new File( getBasedir(), path ).getAbsolutePath();
320 }
321
322 if ( !paths.contains( path ) )
323 {
324 paths.add( path );
325 }
326 }
327 }
328 }
329
330 public void addCompileSourceRoot( String path )
331 {
332 addPath( getCompileSourceRoots(), path );
333 }
334
335 public void addTestCompileSourceRoot( String path )
336 {
337 addPath( getTestCompileSourceRoots(), path );
338 }
339
340 public List<String> getCompileSourceRoots()
341 {
342 return compileSourceRoots;
343 }
344
345 public List<String> getTestCompileSourceRoots()
346 {
347 return testCompileSourceRoots;
348 }
349
350 public List<String> getCompileClasspathElements()
351 throws DependencyResolutionRequiredException
352 {
353 List<String> list = new ArrayList<>( getArtifacts().size() + 1 );
354
355 String d = getBuild().getOutputDirectory();
356 if ( d != null )
357 {
358 list.add( d );
359 }
360
361 for ( Artifact a : getArtifacts() )
362 {
363 if ( a.getArtifactHandler().isAddedToClasspath() )
364 {
365
366 if ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_PROVIDED.equals( a.getScope() )
367 || Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
368 {
369 addArtifactPath( a, list );
370 }
371 }
372 }
373
374 return list;
375 }
376
377
378
379 public List<String> getTestClasspathElements()
380 throws DependencyResolutionRequiredException
381 {
382 List<String> list = new ArrayList<>( getArtifacts().size() + 2 );
383
384 String d = getBuild().getTestOutputDirectory();
385 if ( d != null )
386 {
387 list.add( d );
388 }
389
390 d = getBuild().getOutputDirectory();
391 if ( d != null )
392 {
393 list.add( d );
394 }
395
396 for ( Artifact a : getArtifacts() )
397 {
398 if ( a.getArtifactHandler().isAddedToClasspath() )
399 {
400 addArtifactPath( a, list );
401 }
402 }
403
404 return list;
405 }
406
407 public List<String> getRuntimeClasspathElements()
408 throws DependencyResolutionRequiredException
409 {
410 List<String> list = new ArrayList<>( getArtifacts().size() + 1 );
411
412 String d = getBuild().getOutputDirectory();
413 if ( d != null )
414 {
415 list.add( d );
416 }
417
418 for ( Artifact a : getArtifacts() )
419 {
420 if ( a.getArtifactHandler().isAddedToClasspath()
421
422 && ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_RUNTIME.equals( a.getScope() ) ) )
423 {
424 addArtifactPath( a, list );
425 }
426 }
427 return list;
428 }
429
430
431
432
433
434 public void setModelVersion( String pomVersion )
435 {
436 getModel().setModelVersion( pomVersion );
437 }
438
439 public String getModelVersion()
440 {
441 return getModel().getModelVersion();
442 }
443
444 public String getId()
445 {
446 return getModel().getId();
447 }
448
449 public void setGroupId( String groupId )
450 {
451 getModel().setGroupId( groupId );
452 }
453
454 public String getGroupId()
455 {
456 String groupId = getModel().getGroupId();
457
458 if ( ( groupId == null ) && ( getModel().getParent() != null ) )
459 {
460 groupId = getModel().getParent().getGroupId();
461 }
462
463 return groupId;
464 }
465
466 public void setArtifactId( String artifactId )
467 {
468 getModel().setArtifactId( artifactId );
469 }
470
471 public String getArtifactId()
472 {
473 return getModel().getArtifactId();
474 }
475
476 public void setName( String name )
477 {
478 getModel().setName( name );
479 }
480
481 public String getName()
482 {
483
484 if ( getModel().getName() != null )
485 {
486 return getModel().getName();
487 }
488 else
489 {
490 return getArtifactId();
491 }
492 }
493
494 public void setVersion( String version )
495 {
496 getModel().setVersion( version );
497 }
498
499 public String getVersion()
500 {
501 String version = getModel().getVersion();
502
503 if ( ( version == null ) && ( getModel().getParent() != null ) )
504 {
505 version = getModel().getParent().getVersion();
506 }
507
508 return version;
509 }
510
511 public String getPackaging()
512 {
513 return getModel().getPackaging();
514 }
515
516 public void setPackaging( String packaging )
517 {
518 getModel().setPackaging( packaging );
519 }
520
521 public void setInceptionYear( String inceptionYear )
522 {
523 getModel().setInceptionYear( inceptionYear );
524 }
525
526 public String getInceptionYear()
527 {
528 return getModel().getInceptionYear();
529 }
530
531 public void setUrl( String url )
532 {
533 getModel().setUrl( url );
534 }
535
536 public String getUrl()
537 {
538 return getModel().getUrl();
539 }
540
541 public Prerequisites getPrerequisites()
542 {
543 return getModel().getPrerequisites();
544 }
545
546 public void setIssueManagement( IssueManagement issueManagement )
547 {
548 getModel().setIssueManagement( issueManagement );
549 }
550
551 public CiManagement getCiManagement()
552 {
553 return getModel().getCiManagement();
554 }
555
556 public void setCiManagement( CiManagement ciManagement )
557 {
558 getModel().setCiManagement( ciManagement );
559 }
560
561 public IssueManagement getIssueManagement()
562 {
563 return getModel().getIssueManagement();
564 }
565
566 public void setDistributionManagement( DistributionManagement distributionManagement )
567 {
568 getModel().setDistributionManagement( distributionManagement );
569 }
570
571 public DistributionManagement getDistributionManagement()
572 {
573 return getModel().getDistributionManagement();
574 }
575
576 public void setDescription( String description )
577 {
578 getModel().setDescription( description );
579 }
580
581 public String getDescription()
582 {
583 return getModel().getDescription();
584 }
585
586 public void setOrganization( Organization organization )
587 {
588 getModel().setOrganization( organization );
589 }
590
591 public Organization getOrganization()
592 {
593 return getModel().getOrganization();
594 }
595
596 public void setScm( Scm scm )
597 {
598 getModel().setScm( scm );
599 }
600
601 public Scm getScm()
602 {
603 return getModel().getScm();
604 }
605
606 public void setMailingLists( List<MailingList> mailingLists )
607 {
608 getModel().setMailingLists( mailingLists );
609 }
610
611 public List<MailingList> getMailingLists()
612 {
613 return getModel().getMailingLists();
614 }
615
616 public void addMailingList( MailingList mailingList )
617 {
618 getModel().addMailingList( mailingList );
619 }
620
621 public void setDevelopers( List<Developer> developers )
622 {
623 getModel().setDevelopers( developers );
624 }
625
626 public List<Developer> getDevelopers()
627 {
628 return getModel().getDevelopers();
629 }
630
631 public void addDeveloper( Developer developer )
632 {
633 getModel().addDeveloper( developer );
634 }
635
636 public void setContributors( List<Contributor> contributors )
637 {
638 getModel().setContributors( contributors );
639 }
640
641 public List<Contributor> getContributors()
642 {
643 return getModel().getContributors();
644 }
645
646 public void addContributor( Contributor contributor )
647 {
648 getModel().addContributor( contributor );
649 }
650
651 public void setBuild( Build build )
652 {
653 getModel().setBuild( build );
654 }
655
656 public Build getBuild()
657 {
658 return getModelBuild();
659 }
660
661 public List<Resource> getResources()
662 {
663 return getBuild().getResources();
664 }
665
666 public List<Resource> getTestResources()
667 {
668 return getBuild().getTestResources();
669 }
670
671 public void addResource( Resource resource )
672 {
673 getBuild().addResource( resource );
674 }
675
676 public void addTestResource( Resource testResource )
677 {
678 getBuild().addTestResource( testResource );
679 }
680
681 public void setLicenses( List<License> licenses )
682 {
683 getModel().setLicenses( licenses );
684 }
685
686 public List<License> getLicenses()
687 {
688 return getModel().getLicenses();
689 }
690
691 public void addLicense( License license )
692 {
693 getModel().addLicense( license );
694 }
695
696 public void setArtifacts( Set<Artifact> artifacts )
697 {
698 this.artifacts = artifacts;
699
700
701 artifactMap = null;
702 }
703
704
705
706
707
708
709
710
711
712 public Set<Artifact> getArtifacts()
713 {
714 if ( artifacts == null )
715 {
716 if ( artifactFilter == null || resolvedArtifacts == null )
717 {
718 artifacts = new LinkedHashSet<>();
719 }
720 else
721 {
722 artifacts = new LinkedHashSet<>( resolvedArtifacts.size() * 2 );
723 for ( Artifact artifact : resolvedArtifacts )
724 {
725 if ( artifactFilter.include( artifact ) )
726 {
727 artifacts.add( artifact );
728 }
729 }
730 }
731 }
732 return artifacts;
733 }
734
735 public Map<String, Artifact> getArtifactMap()
736 {
737 if ( artifactMap == null )
738 {
739 artifactMap = ArtifactUtils.artifactMapByVersionlessId( getArtifacts() );
740 }
741 return artifactMap;
742 }
743
744 public void setPluginArtifacts( Set<Artifact> pluginArtifacts )
745 {
746 this.pluginArtifacts = pluginArtifacts;
747
748 this.pluginArtifactMap = null;
749 }
750
751 public Set<Artifact> getPluginArtifacts()
752 {
753 return pluginArtifacts;
754 }
755
756 public Map<String, Artifact> getPluginArtifactMap()
757 {
758 if ( pluginArtifactMap == null )
759 {
760 pluginArtifactMap = ArtifactUtils.artifactMapByVersionlessId( getPluginArtifacts() );
761 }
762
763 return pluginArtifactMap;
764 }
765
766 public void setParentArtifact( Artifact parentArtifact )
767 {
768 this.parentArtifact = parentArtifact;
769 }
770
771 public Artifact getParentArtifact()
772 {
773 return parentArtifact;
774 }
775
776 public List<Repository> getRepositories()
777 {
778 return getModel().getRepositories();
779 }
780
781
782
783
784
785 public List<Plugin> getBuildPlugins()
786 {
787 if ( getModel().getBuild() == null )
788 {
789 return Collections.emptyList();
790 }
791 return Collections.unmodifiableList( getModel().getBuild().getPlugins() );
792 }
793
794 public List<String> getModules()
795 {
796 return getModel().getModules();
797 }
798
799 public PluginManagement getPluginManagement()
800 {
801 PluginManagement pluginMgmt = null;
802
803 Build build = getModel().getBuild();
804 if ( build != null )
805 {
806 pluginMgmt = build.getPluginManagement();
807 }
808
809 return pluginMgmt;
810 }
811
812 private Build getModelBuild()
813 {
814 Build build = getModel().getBuild();
815
816 if ( build == null )
817 {
818 build = new Build();
819
820 getModel().setBuild( build );
821 }
822
823 return build;
824 }
825
826 public void setRemoteArtifactRepositories( List<ArtifactRepository> remoteArtifactRepositories )
827 {
828 this.remoteArtifactRepositories = remoteArtifactRepositories;
829 this.remoteProjectRepositories = RepositoryUtils.toRepos( getRemoteArtifactRepositories() );
830 }
831
832 public List<ArtifactRepository> getRemoteArtifactRepositories()
833 {
834 if ( remoteArtifactRepositories == null )
835 {
836 remoteArtifactRepositories = new ArrayList<>();
837 }
838
839 return remoteArtifactRepositories;
840 }
841
842 public void setPluginArtifactRepositories( List<ArtifactRepository> pluginArtifactRepositories )
843 {
844 this.pluginArtifactRepositories = pluginArtifactRepositories;
845 this.remotePluginRepositories = RepositoryUtils.toRepos( getPluginArtifactRepositories() );
846 }
847
848
849
850
851
852 public List<ArtifactRepository> getPluginArtifactRepositories()
853 {
854 if ( pluginArtifactRepositories == null )
855 {
856 pluginArtifactRepositories = new ArrayList<>();
857 }
858
859 return pluginArtifactRepositories;
860 }
861
862 public ArtifactRepository getDistributionManagementArtifactRepository()
863 {
864 return getArtifact().isSnapshot() && ( getSnapshotArtifactRepository() != null )
865 ? getSnapshotArtifactRepository()
866 : getReleaseArtifactRepository();
867 }
868
869 public List<Repository> getPluginRepositories()
870 {
871 return getModel().getPluginRepositories();
872 }
873
874 public List<RemoteRepository> getRemoteProjectRepositories()
875 {
876 return remoteProjectRepositories;
877 }
878
879 public List<RemoteRepository> getRemotePluginRepositories()
880 {
881 return remotePluginRepositories;
882 }
883
884 public void setActiveProfiles( List<Profile> activeProfiles )
885 {
886 this.activeProfiles = activeProfiles;
887 }
888
889 public List<Profile> getActiveProfiles()
890 {
891 return activeProfiles;
892 }
893
894 public void setInjectedProfileIds( String source, List<String> injectedProfileIds )
895 {
896 if ( injectedProfileIds != null )
897 {
898 this.injectedProfileIds.put( source, new ArrayList<>( injectedProfileIds ) );
899 }
900 else
901 {
902 this.injectedProfileIds.remove( source );
903 }
904 }
905
906
907
908
909
910
911
912
913
914
915
916 public Map<String, List<String>> getInjectedProfileIds()
917 {
918 return this.injectedProfileIds;
919 }
920
921
922
923
924
925
926
927
928
929
930
931
932 public void addAttachedArtifact( Artifact artifact )
933 throws DuplicateArtifactAttachmentException
934 {
935
936 int index = attachedArtifacts.indexOf( artifact );
937 if ( index >= 0 )
938 {
939 LOGGER.warn( "artifact {} already attached, replace previous instance", artifact );
940 attachedArtifacts.set( index, artifact );
941 }
942 else
943 {
944 attachedArtifacts.add( artifact );
945 }
946 }
947
948 public List<Artifact> getAttachedArtifacts()
949 {
950 if ( attachedArtifacts == null )
951 {
952 attachedArtifacts = new ArrayList<>();
953 }
954 return Collections.unmodifiableList( attachedArtifacts );
955 }
956
957 public Xpp3Dom getGoalConfiguration( String pluginGroupId, String pluginArtifactId, String executionId,
958 String goalId )
959 {
960 Xpp3Dom dom = null;
961
962 if ( getBuildPlugins() != null )
963 {
964 for ( Plugin plugin : getBuildPlugins() )
965 {
966 if ( pluginGroupId.equals( plugin.getGroupId() ) && pluginArtifactId.equals( plugin.getArtifactId() ) )
967 {
968 dom = (Xpp3Dom) plugin.getConfiguration();
969
970 if ( executionId != null )
971 {
972 PluginExecution execution = plugin.getExecutionsAsMap().get( executionId );
973 if ( execution != null )
974 {
975
976 dom = (Xpp3Dom) execution.getConfiguration();
977 }
978 }
979 break;
980 }
981 }
982 }
983
984 if ( dom != null )
985 {
986
987 dom = new Xpp3Dom( dom );
988 }
989
990 return dom;
991 }
992
993 public MavenProject getExecutionProject()
994 {
995 return ( executionProject == null ? this : executionProject );
996 }
997
998 public void setExecutionProject( MavenProject executionProject )
999 {
1000 this.executionProject = executionProject;
1001 }
1002
1003 public List<MavenProject> getCollectedProjects()
1004 {
1005 return collectedProjects;
1006 }
1007
1008 public void setCollectedProjects( List<MavenProject> collectedProjects )
1009 {
1010 this.collectedProjects = collectedProjects;
1011 }
1012
1013
1014
1015
1016
1017
1018
1019 @Deprecated
1020 public Set<Artifact> getDependencyArtifacts()
1021 {
1022 return dependencyArtifacts;
1023 }
1024
1025 @Deprecated
1026 public void setDependencyArtifacts( Set<Artifact> dependencyArtifacts )
1027 {
1028 this.dependencyArtifacts = dependencyArtifacts;
1029 }
1030
1031 public void setReleaseArtifactRepository( ArtifactRepository releaseArtifactRepository )
1032 {
1033 this.releaseArtifactRepository = releaseArtifactRepository;
1034 }
1035
1036 public void setSnapshotArtifactRepository( ArtifactRepository snapshotArtifactRepository )
1037 {
1038 this.snapshotArtifactRepository = snapshotArtifactRepository;
1039 }
1040
1041 public void setOriginalModel( Model originalModel )
1042 {
1043 this.originalModel = originalModel;
1044 }
1045
1046 public Model getOriginalModel()
1047 {
1048 return originalModel;
1049 }
1050
1051 public void setManagedVersionMap( Map<String, Artifact> map )
1052 {
1053 managedVersionMap = map;
1054 }
1055
1056 public Map<String, Artifact> getManagedVersionMap()
1057 {
1058 return managedVersionMap;
1059 }
1060
1061 @Override
1062 public boolean equals( Object other )
1063 {
1064 if ( other == this )
1065 {
1066 return true;
1067 }
1068 else if ( !( other instanceof MavenProject ) )
1069 {
1070 return false;
1071 }
1072
1073 MavenProject that = (MavenProject) other;
1074
1075 return Objects.equals( getArtifactId(), that.getArtifactId() )
1076 && Objects.equals( getGroupId(), that.getGroupId() )
1077 && Objects.equals( getVersion(), that.getVersion() );
1078 }
1079
1080 @Override
1081 public int hashCode()
1082 {
1083 int hash = 17;
1084 hash = 31 * hash + getGroupId().hashCode();
1085 hash = 31 * hash + getArtifactId().hashCode();
1086 hash = 31 * hash + getVersion().hashCode();
1087 return hash;
1088 }
1089
1090 public List<Extension> getBuildExtensions()
1091 {
1092 Build build = getBuild();
1093 if ( ( build == null ) || ( build.getExtensions() == null ) )
1094 {
1095 return Collections.emptyList();
1096 }
1097 else
1098 {
1099 return Collections.unmodifiableList( build.getExtensions() );
1100 }
1101 }
1102
1103 public void addProjectReference( MavenProject project )
1104 {
1105 projectReferences.put( getProjectReferenceId( project.getGroupId(), project.getArtifactId(),
1106 project.getVersion() ), project );
1107 }
1108
1109 public Properties getProperties()
1110 {
1111 return getModel().getProperties();
1112 }
1113
1114 public List<String> getFilters()
1115 {
1116 return getBuild().getFilters();
1117 }
1118
1119 public Map<String, MavenProject> getProjectReferences()
1120 {
1121 return projectReferences;
1122 }
1123
1124 public boolean isExecutionRoot()
1125 {
1126 return executionRoot;
1127 }
1128
1129 public void setExecutionRoot( boolean executionRoot )
1130 {
1131 this.executionRoot = executionRoot;
1132 }
1133
1134 public String getDefaultGoal()
1135 {
1136 return getBuild() != null ? getBuild().getDefaultGoal() : null;
1137 }
1138
1139 public Plugin getPlugin( String pluginKey )
1140 {
1141 return getBuild().getPluginsAsMap().get( pluginKey );
1142 }
1143
1144
1145
1146
1147 @Override
1148 public String toString()
1149 {
1150 StringBuilder sb = new StringBuilder( 128 );
1151 sb.append( "MavenProject: " );
1152 sb.append( getGroupId() );
1153 sb.append( ':' );
1154 sb.append( getArtifactId() );
1155 sb.append( ':' );
1156 sb.append( getVersion() );
1157 sb.append( " @ " );
1158
1159 try
1160 {
1161 sb.append( getFile().getPath() );
1162 }
1163 catch ( NullPointerException e )
1164 {
1165
1166 }
1167
1168 return sb.toString();
1169 }
1170
1171
1172
1173
1174 @Override
1175 public MavenProject clone()
1176 {
1177 MavenProject clone;
1178 try
1179 {
1180 clone = (MavenProject) super.clone();
1181 }
1182 catch ( CloneNotSupportedException e )
1183 {
1184 throw new UnsupportedOperationException( e );
1185 }
1186
1187 clone.deepCopy( this );
1188
1189 return clone;
1190 }
1191
1192 public void setModel( Model model )
1193 {
1194 this.model = model;
1195 }
1196
1197 protected void setAttachedArtifacts( List<Artifact> attachedArtifacts )
1198 {
1199 this.attachedArtifacts = attachedArtifacts;
1200 }
1201
1202 protected void setCompileSourceRoots( List<String> compileSourceRoots )
1203 {
1204 this.compileSourceRoots = compileSourceRoots;
1205 }
1206
1207 protected void setTestCompileSourceRoots( List<String> testCompileSourceRoots )
1208 {
1209 this.testCompileSourceRoots = testCompileSourceRoots;
1210 }
1211
1212 protected ArtifactRepository getReleaseArtifactRepository()
1213 {
1214 return releaseArtifactRepository;
1215 }
1216
1217 protected ArtifactRepository getSnapshotArtifactRepository()
1218 {
1219 return snapshotArtifactRepository;
1220 }
1221
1222 private void deepCopy( MavenProject project )
1223 {
1224
1225
1226
1227 file = project.file;
1228 basedir = project.basedir;
1229
1230
1231
1232 if ( project.getDependencyArtifacts() != null )
1233 {
1234 setDependencyArtifacts( Collections.unmodifiableSet( project.getDependencyArtifacts() ) );
1235 }
1236
1237 if ( project.getArtifacts() != null )
1238 {
1239 setArtifacts( Collections.unmodifiableSet( project.getArtifacts() ) );
1240 }
1241
1242 if ( project.getParentFile() != null )
1243 {
1244 parentFile = new File( project.getParentFile().getAbsolutePath() );
1245 }
1246
1247 if ( project.getPluginArtifacts() != null )
1248 {
1249 setPluginArtifacts( Collections.unmodifiableSet( project.getPluginArtifacts() ) );
1250 }
1251
1252 if ( project.getReportArtifacts() != null )
1253 {
1254 setReportArtifacts( Collections.unmodifiableSet( project.getReportArtifacts() ) );
1255 }
1256
1257 if ( project.getExtensionArtifacts() != null )
1258 {
1259 setExtensionArtifacts( Collections.unmodifiableSet( project.getExtensionArtifacts() ) );
1260 }
1261
1262 setParentArtifact( ( project.getParentArtifact() ) );
1263
1264 if ( project.getRemoteArtifactRepositories() != null )
1265 {
1266 setRemoteArtifactRepositories( Collections.unmodifiableList( project.getRemoteArtifactRepositories() ) );
1267 }
1268
1269 if ( project.getPluginArtifactRepositories() != null )
1270 {
1271 setPluginArtifactRepositories( Collections.unmodifiableList( project.getPluginArtifactRepositories() ) );
1272 }
1273
1274 if ( project.getActiveProfiles() != null )
1275 {
1276 setActiveProfiles( ( Collections.unmodifiableList( project.getActiveProfiles() ) ) );
1277 }
1278
1279 if ( project.getAttachedArtifacts() != null )
1280 {
1281
1282 setAttachedArtifacts( new ArrayList<>( project.getAttachedArtifacts() ) );
1283 }
1284
1285 if ( project.getCompileSourceRoots() != null )
1286 {
1287
1288 setCompileSourceRoots( ( new ArrayList<>( project.getCompileSourceRoots() ) ) );
1289 }
1290
1291 if ( project.getTestCompileSourceRoots() != null )
1292 {
1293 setTestCompileSourceRoots( ( new ArrayList<>( project.getTestCompileSourceRoots() ) ) );
1294 }
1295
1296 if ( project.getScriptSourceRoots() != null )
1297 {
1298 setScriptSourceRoots( ( new ArrayList<>( project.getScriptSourceRoots() ) ) );
1299 }
1300
1301 if ( project.getModel() != null )
1302 {
1303 setModel( project.getModel().clone() );
1304 }
1305
1306 if ( project.getOriginalModel() != null )
1307 {
1308 setOriginalModel( project.getOriginalModel() );
1309 }
1310
1311 setExecutionRoot( project.isExecutionRoot() );
1312
1313 if ( project.getArtifact() != null )
1314 {
1315 setArtifact( ArtifactUtils.copyArtifact( project.getArtifact() ) );
1316 }
1317
1318 if ( project.getManagedVersionMap() != null )
1319 {
1320 setManagedVersionMap( project.getManagedVersionMap() );
1321 }
1322
1323 lifecyclePhases.addAll( project.lifecyclePhases );
1324 }
1325
1326 private void addArtifactPath( Artifact artifact, List<String> classpath )
1327 {
1328 File file = artifact.getFile();
1329 if ( file != null )
1330 {
1331 classpath.add( file.getPath() );
1332 }
1333 }
1334
1335 private static String getProjectReferenceId( String groupId, String artifactId, String version )
1336 {
1337 StringBuilder buffer = new StringBuilder( 128 );
1338 buffer.append( groupId ).append( ':' ).append( artifactId ).append( ':' ).append( version );
1339 return buffer.toString();
1340 }
1341
1342
1343
1344
1345
1346
1347 public void setContextValue( String key, Object value )
1348 {
1349 if ( context == null )
1350 {
1351 context = new HashMap<>();
1352 }
1353 if ( value != null )
1354 {
1355 context.put( key, value );
1356 }
1357 else
1358 {
1359 context.remove( key );
1360 }
1361 }
1362
1363
1364
1365
1366 public Object getContextValue( String key )
1367 {
1368 if ( context == null )
1369 {
1370 return null;
1371 }
1372 return context.get( key );
1373 }
1374
1375
1376
1377
1378
1379
1380
1381
1382 public void setClassRealm( ClassRealm classRealm )
1383 {
1384 this.classRealm = classRealm;
1385 }
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395 public ClassRealm getClassRealm()
1396 {
1397 return classRealm;
1398 }
1399
1400
1401
1402
1403
1404
1405
1406
1407 public void setExtensionDependencyFilter( DependencyFilter extensionDependencyFilter )
1408 {
1409 this.extensionDependencyFilter = extensionDependencyFilter;
1410 }
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420 public DependencyFilter getExtensionDependencyFilter()
1421 {
1422 return extensionDependencyFilter;
1423 }
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433 public void setResolvedArtifacts( Set<Artifact> artifacts )
1434 {
1435 this.resolvedArtifacts = ( artifacts != null ) ? artifacts : Collections.<Artifact>emptySet();
1436 this.artifacts = null;
1437 this.artifactMap = null;
1438 }
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448 public void setArtifactFilter( ArtifactFilter artifactFilter )
1449 {
1450 this.artifactFilter = artifactFilter;
1451 this.artifacts = null;
1452 this.artifactMap = null;
1453 }
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463 public boolean hasLifecyclePhase( String phase )
1464 {
1465 return lifecyclePhases.contains( phase );
1466 }
1467
1468
1469
1470
1471
1472
1473
1474
1475 public void addLifecyclePhase( String lifecyclePhase )
1476 {
1477 lifecyclePhases.add( lifecyclePhase );
1478 }
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492 private ProjectBuildingRequest projectBuilderConfiguration;
1493
1494 private Map<String, String> moduleAdjustments;
1495
1496 @Deprecated
1497 public String getModulePathAdjustment( MavenProject moduleProject )
1498 throws IOException
1499 {
1500
1501
1502 String module = moduleProject.getArtifactId();
1503
1504 File moduleFile = moduleProject.getFile();
1505
1506 if ( moduleFile != null )
1507 {
1508 File moduleDir = moduleFile.getCanonicalFile().getParentFile();
1509
1510 module = moduleDir.getName();
1511 }
1512
1513 if ( moduleAdjustments == null )
1514 {
1515 moduleAdjustments = new HashMap<>();
1516
1517 List<String> modules = getModules();
1518 if ( modules != null )
1519 {
1520 for ( String modulePath : modules )
1521 {
1522 String moduleName = modulePath;
1523
1524 if ( moduleName.endsWith( "/" ) || moduleName.endsWith( "\\" ) )
1525 {
1526 moduleName = moduleName.substring( 0, moduleName.length() - 1 );
1527 }
1528
1529 int lastSlash = moduleName.lastIndexOf( '/' );
1530
1531 if ( lastSlash < 0 )
1532 {
1533 lastSlash = moduleName.lastIndexOf( '\\' );
1534 }
1535
1536 String adjustment = null;
1537
1538 if ( lastSlash > -1 )
1539 {
1540 moduleName = moduleName.substring( lastSlash + 1 );
1541 adjustment = modulePath.substring( 0, lastSlash );
1542 }
1543
1544 moduleAdjustments.put( moduleName, adjustment );
1545 }
1546 }
1547 }
1548
1549 return moduleAdjustments.get( module );
1550 }
1551
1552 @Deprecated
1553 public Set<Artifact> createArtifacts( ArtifactFactory artifactFactory, String inheritedScope,
1554 ArtifactFilter filter )
1555 throws InvalidDependencyVersionException
1556 {
1557 return MavenMetadataSource.createArtifacts( artifactFactory, getDependencies(), inheritedScope, filter, this );
1558 }
1559
1560 @Deprecated
1561 protected void setScriptSourceRoots( List<String> scriptSourceRoots )
1562 {
1563 this.scriptSourceRoots = scriptSourceRoots;
1564 }
1565
1566 @Deprecated
1567 public void addScriptSourceRoot( String path )
1568 {
1569 if ( path != null )
1570 {
1571 path = path.trim();
1572 if ( path.length() != 0 )
1573 {
1574 if ( !getScriptSourceRoots().contains( path ) )
1575 {
1576 getScriptSourceRoots().add( path );
1577 }
1578 }
1579 }
1580 }
1581
1582 @Deprecated
1583 public List<String> getScriptSourceRoots()
1584 {
1585 return scriptSourceRoots;
1586 }
1587
1588 @Deprecated
1589 public List<Artifact> getCompileArtifacts()
1590 {
1591 List<Artifact> list = new ArrayList<>( getArtifacts().size() );
1592
1593 for ( Artifact a : getArtifacts() )
1594 {
1595
1596 if ( a.getArtifactHandler().isAddedToClasspath() )
1597 {
1598
1599 if ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_PROVIDED.equals( a.getScope() )
1600 || Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
1601 {
1602 list.add( a );
1603 }
1604 }
1605 }
1606 return list;
1607 }
1608
1609 @Deprecated
1610 public List<Dependency> getCompileDependencies()
1611 {
1612 Set<Artifact> artifacts = getArtifacts();
1613
1614 if ( ( artifacts == null ) || artifacts.isEmpty() )
1615 {
1616 return Collections.emptyList();
1617 }
1618
1619 List<Dependency> list = new ArrayList<>( artifacts.size() );
1620
1621 for ( Artifact a : getArtifacts() )
1622 {
1623
1624 if ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_PROVIDED.equals( a.getScope() )
1625 || Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
1626 {
1627 Dependency dependency = new Dependency();
1628
1629 dependency.setArtifactId( a.getArtifactId() );
1630 dependency.setGroupId( a.getGroupId() );
1631 dependency.setVersion( a.getVersion() );
1632 dependency.setScope( a.getScope() );
1633 dependency.setType( a.getType() );
1634 dependency.setClassifier( a.getClassifier() );
1635
1636 list.add( dependency );
1637 }
1638 }
1639 return Collections.unmodifiableList( list );
1640 }
1641
1642 @Deprecated
1643 public List<Artifact> getTestArtifacts()
1644 {
1645 List<Artifact> list = new ArrayList<>( getArtifacts().size() );
1646
1647 for ( Artifact a : getArtifacts() )
1648 {
1649
1650 if ( a.getArtifactHandler().isAddedToClasspath() )
1651 {
1652 list.add( a );
1653 }
1654 }
1655 return list;
1656 }
1657
1658 @Deprecated
1659 public List<Dependency> getTestDependencies()
1660 {
1661 Set<Artifact> artifacts = getArtifacts();
1662
1663 if ( ( artifacts == null ) || artifacts.isEmpty() )
1664 {
1665 return Collections.emptyList();
1666 }
1667
1668 List<Dependency> list = new ArrayList<>( artifacts.size() );
1669
1670 for ( Artifact a : getArtifacts() )
1671 {
1672 Dependency dependency = new Dependency();
1673
1674 dependency.setArtifactId( a.getArtifactId() );
1675 dependency.setGroupId( a.getGroupId() );
1676 dependency.setVersion( a.getVersion() );
1677 dependency.setScope( a.getScope() );
1678 dependency.setType( a.getType() );
1679 dependency.setClassifier( a.getClassifier() );
1680
1681 list.add( dependency );
1682 }
1683 return Collections.unmodifiableList( list );
1684 }
1685
1686 @Deprecated
1687 public List<Dependency> getRuntimeDependencies()
1688 {
1689 Set<Artifact> artifacts = getArtifacts();
1690
1691 if ( ( artifacts == null ) || artifacts.isEmpty() )
1692 {
1693 return Collections.emptyList();
1694 }
1695
1696 List<Dependency> list = new ArrayList<>( artifacts.size() );
1697
1698 for ( Artifact a : getArtifacts() )
1699 {
1700
1701 if ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_RUNTIME.equals( a.getScope() ) )
1702 {
1703 Dependency dependency = new Dependency();
1704
1705 dependency.setArtifactId( a.getArtifactId() );
1706 dependency.setGroupId( a.getGroupId() );
1707 dependency.setVersion( a.getVersion() );
1708 dependency.setScope( a.getScope() );
1709 dependency.setType( a.getType() );
1710 dependency.setClassifier( a.getClassifier() );
1711
1712 list.add( dependency );
1713 }
1714 }
1715 return Collections.unmodifiableList( list );
1716 }
1717
1718 @Deprecated
1719 public List<Artifact> getRuntimeArtifacts()
1720 {
1721 List<Artifact> list = new ArrayList<>( getArtifacts().size() );
1722
1723 for ( Artifact a : getArtifacts() )
1724 {
1725
1726 if ( a.getArtifactHandler().isAddedToClasspath()
1727
1728 && ( Artifact.SCOPE_COMPILE.equals( a.getScope() ) || Artifact.SCOPE_RUNTIME.equals( a.getScope() ) ) )
1729 {
1730 list.add( a );
1731 }
1732 }
1733 return list;
1734 }
1735
1736 @Deprecated
1737 public List<String> getSystemClasspathElements()
1738 throws DependencyResolutionRequiredException
1739 {
1740 List<String> list = new ArrayList<>( getArtifacts().size() );
1741
1742 String d = getBuild().getOutputDirectory();
1743 if ( d != null )
1744 {
1745 list.add( d );
1746 }
1747
1748 for ( Artifact a : getArtifacts() )
1749 {
1750 if ( a.getArtifactHandler().isAddedToClasspath() )
1751 {
1752
1753 if ( Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
1754 {
1755 addArtifactPath( a, list );
1756 }
1757 }
1758 }
1759 return list;
1760 }
1761
1762 @Deprecated
1763 public List<Artifact> getSystemArtifacts()
1764 {
1765 List<Artifact> list = new ArrayList<>( getArtifacts().size() );
1766
1767 for ( Artifact a : getArtifacts() )
1768 {
1769
1770 if ( a.getArtifactHandler().isAddedToClasspath() )
1771 {
1772
1773 if ( Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
1774 {
1775 list.add( a );
1776 }
1777 }
1778 }
1779 return list;
1780 }
1781
1782 @Deprecated
1783 public List<Dependency> getSystemDependencies()
1784 {
1785 Set<Artifact> artifacts = getArtifacts();
1786
1787 if ( ( artifacts == null ) || artifacts.isEmpty() )
1788 {
1789 return Collections.emptyList();
1790 }
1791
1792 List<Dependency> list = new ArrayList<>( artifacts.size() );
1793
1794 for ( Artifact a : getArtifacts() )
1795 {
1796
1797 if ( Artifact.SCOPE_SYSTEM.equals( a.getScope() ) )
1798 {
1799 Dependency dependency = new Dependency();
1800
1801 dependency.setArtifactId( a.getArtifactId() );
1802 dependency.setGroupId( a.getGroupId() );
1803 dependency.setVersion( a.getVersion() );
1804 dependency.setScope( a.getScope() );
1805 dependency.setType( a.getType() );
1806 dependency.setClassifier( a.getClassifier() );
1807
1808 list.add( dependency );
1809 }
1810 }
1811 return Collections.unmodifiableList( list );
1812 }
1813
1814 @Deprecated
1815 public void setReporting( Reporting reporting )
1816 {
1817 getModel().setReporting( reporting );
1818 }
1819
1820 @Deprecated
1821 public Reporting getReporting()
1822 {
1823 return getModel().getReporting();
1824 }
1825
1826 @Deprecated
1827 public void setReportArtifacts( Set<Artifact> reportArtifacts )
1828 {
1829 this.reportArtifacts = reportArtifacts;
1830
1831 reportArtifactMap = null;
1832 }
1833
1834 @Deprecated
1835 public Set<Artifact> getReportArtifacts()
1836 {
1837 return reportArtifacts;
1838 }
1839
1840 @Deprecated
1841 public Map<String, Artifact> getReportArtifactMap()
1842 {
1843 if ( reportArtifactMap == null )
1844 {
1845 reportArtifactMap = ArtifactUtils.artifactMapByVersionlessId( getReportArtifacts() );
1846 }
1847
1848 return reportArtifactMap;
1849 }
1850
1851 @Deprecated
1852 public void setExtensionArtifacts( Set<Artifact> extensionArtifacts )
1853 {
1854 this.extensionArtifacts = extensionArtifacts;
1855
1856 extensionArtifactMap = null;
1857 }
1858
1859 @Deprecated
1860 public Set<Artifact> getExtensionArtifacts()
1861 {
1862 return extensionArtifacts;
1863 }
1864
1865 @Deprecated
1866 public Map<String, Artifact> getExtensionArtifactMap()
1867 {
1868 if ( extensionArtifactMap == null )
1869 {
1870 extensionArtifactMap = ArtifactUtils.artifactMapByVersionlessId( getExtensionArtifacts() );
1871 }
1872
1873 return extensionArtifactMap;
1874 }
1875
1876 @Deprecated
1877 public List<ReportPlugin> getReportPlugins()
1878 {
1879 if ( getModel().getReporting() == null )
1880 {
1881 return Collections.emptyList();
1882 }
1883 return Collections.unmodifiableList( getModel().getReporting().getPlugins() );
1884 }
1885
1886 @Deprecated
1887 public Xpp3Dom getReportConfiguration( String pluginGroupId, String pluginArtifactId, String reportSetId )
1888 {
1889 Xpp3Dom dom = null;
1890
1891
1892
1893
1894
1895
1896
1897 if ( getReportPlugins() != null )
1898 {
1899 for ( ReportPlugin plugin : getReportPlugins() )
1900 {
1901 if ( pluginGroupId.equals( plugin.getGroupId() ) && pluginArtifactId.equals( plugin.getArtifactId() ) )
1902 {
1903 dom = (Xpp3Dom) plugin.getConfiguration();
1904
1905 if ( reportSetId != null )
1906 {
1907 ReportSet reportSet = plugin.getReportSetsAsMap().get( reportSetId );
1908 if ( reportSet != null )
1909 {
1910 Xpp3Dom executionConfiguration = (Xpp3Dom) reportSet.getConfiguration();
1911 if ( executionConfiguration != null )
1912 {
1913 Xpp3Dom newDom = new Xpp3Dom( executionConfiguration );
1914 dom = Xpp3Dom.mergeXpp3Dom( newDom, dom );
1915 }
1916 }
1917 }
1918 break;
1919 }
1920 }
1921 }
1922
1923 if ( dom != null )
1924 {
1925
1926 dom = new Xpp3Dom( dom );
1927 }
1928
1929 return dom;
1930 }
1931
1932
1933
1934
1935 @Deprecated
1936 public void attachArtifact( String type, String classifier, File file )
1937 {
1938 }
1939
1940
1941
1942
1943 @Deprecated
1944 public void writeModel( Writer writer )
1945 throws IOException
1946 {
1947 MavenXpp3Writer pomWriter = new MavenXpp3Writer();
1948 pomWriter.write( writer, getModel() );
1949 }
1950
1951
1952
1953
1954 @Deprecated
1955 public void writeOriginalModel( Writer writer )
1956 throws IOException
1957 {
1958 MavenXpp3Writer pomWriter = new MavenXpp3Writer();
1959 pomWriter.write( writer, getOriginalModel() );
1960 }
1961
1962 @Deprecated
1963 public Artifact replaceWithActiveArtifact( Artifact pluginArtifact )
1964 {
1965 return pluginArtifact;
1966 }
1967
1968
1969
1970
1971
1972
1973
1974
1975 @Deprecated
1976 public ProjectBuildingRequest getProjectBuildingRequest()
1977 {
1978 return projectBuilderConfiguration;
1979 }
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989 @Deprecated
1990 public void setProjectBuildingRequest( ProjectBuildingRequest projectBuildingRequest )
1991 {
1992 this.projectBuilderConfiguration = projectBuildingRequest;
1993 }
1994 }