\r
\r
<bean class="jetbrains.buildServer.nuget.server.exec.NuGetExecutorImpl"/>\r
+ <bean class="jetbrains.buildServer.nuget.server.exec.ListPackagesCommand"/>\r
\r
+ <bean class="jetbrains.buildServer.nuget.server.trigger.ThreadedBuildTriggetFactoryImpl"/>\r
+ <bean class="jetbrains.buildServer.nuget.server.trigger.NamedPackagesUpdateChecker"/>\r
<bean class="jetbrains.buildServer.nuget.server.trigger.NuGetSimpleTrigger"/>\r
</beans>
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright 2000-2011 JetBrains s.r.o.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package jetbrains.buildServer.nuget.server.trigger;\r
+\r
+import org.jetbrains.annotations.NotNull;\r
+\r
+/**\r
+* Created by Eugene Petrenko (eugene.petrenko@gmail.com)\r
+* Date: 14.07.11 15:57\r
+*/\r
+public class BuildStartReason {\r
+ private final String myReason;\r
+\r
+ public BuildStartReason(@NotNull final String reason) {\r
+ myReason = reason;\r
+ }\r
+\r
+ @NotNull\r
+ public String getReason() {\r
+ return myReason;\r
+ }\r
+}\r
--- /dev/null
+package jetbrains.buildServer.nuget.server.trigger;\r
+\r
+import jetbrains.buildServer.buildTriggers.BuildTriggerDescriptor;\r
+import jetbrains.buildServer.buildTriggers.BuildTriggerException;\r
+import jetbrains.buildServer.nuget.server.exec.ListPackagesCommand;\r
+import jetbrains.buildServer.nuget.server.exec.PackageInfo;\r
+import jetbrains.buildServer.serverSide.CustomDataStorage;\r
+import org.jetbrains.annotations.NotNull;\r
+\r
+import java.util.*;\r
+\r
+/**\r
+ * Created by Eugene Petrenko (eugene.petrenko@gmail.com)\r
+ * Date: 14.07.11 15:41\r
+ */\r
+public class NamedPackagesUpdateChecker implements TriggerUpdateChecker {\r
+ public static final String KEY = "hash";\r
+ private final ListPackagesCommand myCommand;\r
+\r
+ public NamedPackagesUpdateChecker(@NotNull final ListPackagesCommand command) {\r
+ myCommand = command;\r
+ }\r
+\r
+ public BuildStartReason checkChanges(@NotNull BuildTriggerDescriptor descriptor,\r
+ @NotNull CustomDataStorage storage) throws BuildTriggerException {\r
+ final String pkgId = descriptor.getProperties().get(TriggerConstants.PACKAGE);\r
+ final String version = descriptor.getProperties().get(TriggerConstants.VERSION);\r
+ final String source = descriptor.getProperties().get(TriggerConstants.SOURCE);\r
+ Collection<PackageInfo> result = myCommand.checkForChanges(source, pkgId, version);\r
+ final String hash = serializeHashcode(result);\r
+\r
+ String oldHash = storage.getValue(KEY);\r
+ if (!hash.equals(oldHash)) {\r
+ storage.putValue(KEY, hash);\r
+ storage.flush();\r
+ return new BuildStartReason("NuGet Package " + pkgId + " updated");\r
+ }\r
+\r
+ return null;\r
+ }\r
+\r
+ private String serializeHashcode(@NotNull final Collection<PackageInfo> _packages) {\r
+ List<PackageInfo> sorted = new ArrayList<PackageInfo>(_packages);\r
+ Collections.sort(sorted, new Comparator<PackageInfo>() {\r
+ public int compare(PackageInfo o1, PackageInfo o2) {\r
+ int i;\r
+ if (0 != (i = o1.getSource().compareTo(o2.getSource()))) return i;\r
+ if (0 != (i = o1.getPackageId().compareTo(o2.getPackageId()))) return i;\r
+ if (0 != (i = o1.getVersion().compareTo(o2.getVersion()))) return i;\r
+ return 0;\r
+ }\r
+ });\r
+\r
+ StringBuilder sb = new StringBuilder();\r
+ for (PackageInfo info : sorted) {\r
+ sb.append("|s:").append(info.getSource());\r
+ sb.append("|p:").append(info.getPackageId());\r
+ sb.append("|v:").append(info.getVersion());\r
+ }\r
+ return sb.toString();\r
+ }\r
+}\r
package jetbrains.buildServer.nuget.server.trigger;\r
\r
-import jetbrains.buildServer.buildTriggers.*;\r
+import jetbrains.buildServer.buildTriggers.BuildTriggerDescriptor;\r
+import jetbrains.buildServer.buildTriggers.BuildTriggerService;\r
+import jetbrains.buildServer.buildTriggers.BuildTriggeringPolicy;\r
import jetbrains.buildServer.serverSide.InvalidProperty;\r
import jetbrains.buildServer.serverSide.PropertiesProcessor;\r
import jetbrains.buildServer.util.StringUtil;\r
*/\r
public class NuGetSimpleTrigger extends BuildTriggerService {\r
private final PluginDescriptor myDescriptor;\r
+ private BuildTriggeringPolicy myPolicy;\r
\r
- public NuGetSimpleTrigger(@NotNull final PluginDescriptor descriptor) {\r
+ public NuGetSimpleTrigger(@NotNull final PluginDescriptor descriptor,\r
+ @NotNull final ThreadedBuildTriggetFactory factory,\r
+ @NotNull final NamedPackagesUpdateChecker checker) {\r
myDescriptor = descriptor;\r
+ myPolicy = factory.createTrigger(checker);\r
}\r
\r
@NotNull\r
@NotNull\r
@Override\r
public BuildTriggeringPolicy getBuildTriggeringPolicy() {\r
- return new PolledBuildTrigger() {\r
- @Override\r
- public void triggerBuild(@NotNull final PolledTriggerContext context) throws BuildTriggerException {\r
- }\r
- };\r
+ return myPolicy;\r
}\r
\r
@Override\r
--- /dev/null
+/*\r
+ * Copyright 2000-2011 JetBrains s.r.o.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package jetbrains.buildServer.nuget.server.trigger;\r
+\r
+import jetbrains.buildServer.buildTriggers.BuildTriggeringPolicy;\r
+import org.jetbrains.annotations.NotNull;\r
+\r
+/**\r
+ * Factory for thread-based build triggers\r
+ * Created by Eugene Petrenko (eugene.petrenko@gmail.com)\r
+ * Date: 14.07.11 15:25\r
+ */\r
+public interface ThreadedBuildTriggetFactory {\r
+\r
+ /**\r
+ * Creates background thread powered BuildTriggerPolicy implamentation\r
+ * for a given TriggerUpdateChecker.\r
+ * @param updateChecker checker that would be called from background thread\r
+ * @return build triggering policy\r
+ */\r
+ public BuildTriggeringPolicy createTrigger(@NotNull TriggerUpdateChecker updateChecker);\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2000-2011 JetBrains s.r.o.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package jetbrains.buildServer.nuget.server.trigger;\r
+\r
+import jetbrains.buildServer.buildTriggers.BuildTriggeringPolicy;\r
+import jetbrains.buildServer.serverSide.executors.ExecutorServices;\r
+import org.jetbrains.annotations.NotNull;\r
+\r
+/**\r
+ * Created by Eugene Petrenko (eugene.petrenko@gmail.com)\r
+ * Date: 14.07.11 15:31\r
+ */\r
+public class ThreadedBuildTriggetFactoryImpl implements ThreadedBuildTriggetFactory{\r
+ private final ExecutorServices myExecutors;\r
+\r
+ public ThreadedBuildTriggetFactoryImpl(@NotNull final ExecutorServices executors) {\r
+ myExecutors = executors;\r
+ }\r
+\r
+ public BuildTriggeringPolicy createTrigger(@NotNull TriggerUpdateChecker updateChecker) {\r
+ return new ThreaedBuildTriggetPolicy(myExecutors.getLowPriorityExecutorService(), updateChecker);\r
+ }\r
+}\r
import jetbrains.buildServer.buildTriggers.PolledTriggerContext;\r
import org.jetbrains.annotations.NotNull;\r
\r
-import java.util.concurrent.*;\r
+import java.util.concurrent.Callable;\r
+import java.util.concurrent.ExecutionException;\r
+import java.util.concurrent.ExecutorService;\r
+import java.util.concurrent.Future;\r
\r
/**\r
* Created by Eugene Petrenko (eugene.petrenko@gmail.com)\r
* Date: 12.07.11 23:29\r
*/\r
-public class NuGetTriggerPolicy extends PolledBuildTrigger{\r
+public class ThreaedBuildTriggetPolicy extends PolledBuildTrigger {\r
private final ExecutorService myExecutor;\r
- private Future<Boolean> myUpdateRequired;\r
+ private final TriggerUpdateChecker myUpdater;\r
+ private Future<BuildStartReason> myUpdateRequired;\r
\r
- public NuGetTriggerPolicy(@NotNull final ExecutorService executor) {\r
+ public ThreaedBuildTriggetPolicy(@NotNull final ExecutorService executor,\r
+ @NotNull final TriggerUpdateChecker updater) {\r
myExecutor = executor;\r
+ myUpdater = updater;\r
}\r
\r
@Override\r
public synchronized void triggerBuild(@NotNull PolledTriggerContext context) throws BuildTriggerException {\r
if (myUpdateRequired == null) {\r
- myUpdateRequired = myExecutor.submit(createUpdateTask());\r
+ myUpdateRequired = myExecutor.submit(createUpdateTask(context));\r
}\r
\r
if (!myUpdateRequired.isDone()) return;\r
\r
- Boolean result;\r
+ BuildStartReason result;\r
try {\r
result = myUpdateRequired.get();\r
} catch (InterruptedException e) {\r
return;\r
} catch (ExecutionException e) {\r
Throwable cause = e.getCause();\r
+ if (cause instanceof BuildTriggerException) throw (BuildTriggerException)cause;\r
throw new BuildTriggerException(cause.getMessage(), cause);\r
} finally {\r
myUpdateRequired = null;\r
}\r
\r
- if (Boolean.TRUE.equals(result)) {\r
- String packageName = context.getTriggerDescriptor().getProperties().get(TriggerConstants.PACKAGE);\r
- context.getBuildType().addToQueue("NuGet Package " + packageName + " updated");\r
+ if (result != null) {\r
+ context.getBuildType().addToQueue(result.getReason());\r
}\r
}\r
\r
- private Callable<Boolean> createUpdateTask() {\r
- return new Callable<Boolean>() {\r
- public Boolean call() throws Exception {\r
- return null;\r
+ @NotNull\r
+ private Callable<BuildStartReason> createUpdateTask(@NotNull final PolledTriggerContext storage) {\r
+ return new Callable<BuildStartReason>() {\r
+ public BuildStartReason call() throws Exception {\r
+ return myUpdater.checkChanges(storage.getTriggerDescriptor(), storage.getCustomDataStorage());\r
}\r
};\r
}\r
-\r
-\r
}\r
--- /dev/null
+/*\r
+ * Copyright 2000-2011 JetBrains s.r.o.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package jetbrains.buildServer.nuget.server.trigger;\r
+\r
+import jetbrains.buildServer.buildTriggers.BuildTriggerDescriptor;\r
+import jetbrains.buildServer.buildTriggers.BuildTriggerException;\r
+import jetbrains.buildServer.serverSide.CustomDataStorage;\r
+import org.jetbrains.annotations.NotNull;\r
+import org.jetbrains.annotations.Nullable;\r
+\r
+/**\r
+ * Created by Eugene Petrenko (eugene.petrenko@gmail.com)\r
+ * Date: 14.07.11 15:34\r
+ */\r
+public interface TriggerUpdateChecker {\r
+ /**\r
+ * Called from background thread to check for updates\r
+ *\r
+ * @param descriptor build trigger desciptor to check for parameters\r
+ * @param storage trigger state\r
+ * @return null or StartReason instance to start a build\r
+ * @throws jetbrains.buildServer.buildTriggers.BuildTriggerException\r
+ * on error\r
+ */\r
+ @Nullable\r
+ BuildStartReason checkChanges(@NotNull BuildTriggerDescriptor descriptor,\r
+ @NotNull CustomDataStorage storage) throws BuildTriggerException;\r
+}\r