Artifactory seems to automatically generate properties for RPMs, Python wheels etc. Can I extend this function for my own file formats?
I've read the documentation and this talks about the REST API etc but I want to have Artifactory pull properties straight out of the file that I'm uploading.
None yet - I'm asking how.
The logic that automatically generates properties for RPMs etc is hardcoded into each package type Artifactory supports, and you can't add custom repository types.
What you can do is write a user plugin which runs whenever a file is uploaded, reads the file, and adds the appropriate properties. For example:
storage {
afterCreate { item ->
if (!item.isFolder() && item.name.endsWith(".customext")) {
def fstream = repositories.getContent(item.repoPath).inputStream
// read fstream and generate properties
repositories.setProperty(item.repoPath, propName, propVal)
}
}
}
Some notes:
The language is Groovy. If you aren't familiar with Groovy, in a pinch you can pretend it's Java, since most Java is also valid Groovy.
User plugin documentation is here
User plugin API Javadoc is here
For reference, the officially supported plugins are all here
Related
We want to prevent downloading artifacts without build info with a user plugin in our on-prem Artifactory installation. We are struggling to find a connection between the Request and the corresponding BuildInfo.
import org.artifactory.request.Request
import org.artifactory.repo.RepoPath
download {
beforeDownloadRequest { Request request, RepoPath repoPath ->
if (isRelease(repoPath.repoKey)) {
log.warn "Is a release artifact"
// How to verify build info here??
}
}
}
def isRelease(String repoKey) {
return repoKey in ["libs-release-local"]
}
Using the Artifactory Query Language you can find builds based on an artifact, and if the result is empty, then there is no such a build: https://www.jfrog.com/confluence/display/JFROG/Artifactory+Query+Language
For example:
builds.find({"module.artifact.item.name": "artifactory.war"})
Also artifacts linked to a build will have a property "build.number" and "build.name", so that's one way to approach it
The proper solution would be to use JFrog Xray. You can then set scans for your builds, so that all artifacts part of a build will get scanned (plus you get security and license compliance checks there too), and then block the download of unscanned artifacts
Lastly, when you create a build you can also promote it, for instance from "staging" to "release" and on that operation copy or move the artifacts to a repository that is build-release only.
The properties "build.name" and "build.number" are likely the best way for what you are trying to do.
I need to create a backup service so I intend to save the SQLite database file on each platform. The saved file should be available after the uninstall of the app.
I intend to use the Downloads folder (which should be available on every platform).
I have created an interface and use the following code per platform:
Interface:
public interface IBackupService
{
string GetDownloadPath();
}
Android:
public string GetDownloadPath()
{
return Android.OS.Environment.DirectoryDownloads;
}
UWP:
public string GetDownloadPath()
{
return Windows.Storage.KnownFolders.???????;
}
What should I do about that? Is there a public library that I could use?
There does not seem to be a general downloads folder as per this documentation on KnownFolders. So your assumption on the Downloads folder being on every platform doesn't seem to be correct.
If we dive in a bit further we get to the DocumentsLibrary which seems the obvious choice for this kind of purpose, but it is not. Microsoft says:
The Documents library is not intended for general use. For more info,
see App capability declarations. Also, see the following blog post.
Dealing with Documents: How (not) to use the documentsLibrary capability in Windows Store apps
The paragraph after that seems to describe what we have to do then;
If your app has to create and update files that only your app uses,
consider using the app's local folder. Get the app's local folder from
the Windows.Storage.ApplicationData.Current.LocalFolder property.
So, as I can extract from your question you only want to use storage for your app, so the Windows.Storage.ApplicationData.Current.LocalFolder seems to be the right choice according to Microsoft.
In my symfony2 application, i have set up what's necessary to change the locale.
Now I can use the trans features of the bundle and generate the language files under app/resources/translations
That works fine but I feel it's not efficient to edit yml files by hand, and it's advised to use xliff which is absolutely not user friendly.
Plus, in a collaborative environment, I don't see how this could properly work. I'm not sure translators would like git commands.
To those who have already implemented a translation process : how did you do ? how do you organize it ?
Thanks a lot
I used JMSTranslationBundle https://github.com/schmittjoh/JMSTranslationBundle to manage my translations on a project. You use the usual |trans on the variables you want to translate. And then you use a command with app/console for this bundle, and it builds your yml files for you (you have the option to pick the output file type). It also has a translation UI. And if you add new words, no problem, you just rerun the command, it adds the new words to your existing words without losing the original translation.
I'm using only YAML files, but they are located in each bundle, not in the app folder. This is the better way if you want to get clean code. If your translation files are in the app folder, you need to extract the content for a bundle you want to use in another project.
If you use a good IDE like PhpStorm, YAML is no problem and the easiest way to edit YAML. Don't forget the symfony plugin for PhpStorm!
EDIT:
You can also use this bundle. It provides a web interface for translations: http://jmsyst.com/bundles/JMSTranslationBundle#documentation
I have implemented manageable translations for one of my project you can refer to My answer similar to this topic what i have done i have created a service which loads all the translations from my repository.I have 2 entities for this
Language
Language entity holds all the languages which has 2 properties locale and name
locale (en,fr,ar ...)
name (english,french ...)
LanguageTranslation
LanguageTranslation entity holds all the translations with properties
catalogue
translation
language (translation language )
languageToken (key for translation)
Now all your translations are cached by symfony in prod/dev folder so each time when user updates or adds new translation i have cleared translations cache programmatically i was using sonata admin so i added a call to this function in prePersist and preUpdate you can also use doctrine event listeners prePersist/preUpdate for this
private function clearLanguageCache(){
$cacheDir = __DIR__ . "cache folder path"; /** path to app/cache*/
$finder = new \Symfony\Component\Finder\Finder();
$finder->in(array($cacheDir . "/dev/translations", $cacheDir . "/prod/translations"))->files();
foreach($finder as $file){
unlink($file->getRealpath());
}
}
This part is missing in my previous answer for clearing cache
I have an Alfresco module that I would like to have do some cleanup when a new version of it is installed.
In the current situation, an older version of the module created a folder node with custom properties at the root of the repository. We've since decided to have multiple such nodes, and none of them at that location. I'd like to put into the next version of the module code that would run at Alfresco startup, check for the existence of the old node, copy its properties into the appropriate new nodes, and delete the old node.
Is such a thing possible? I've looked at the Bootstrap configuration file, but that appears to only allow one to add things to the repository, not modify or delete them.
My suggestion is that you write a patch. That is a class that implements
org.alfresco.repo.admin.patch.AbstractPatch
Then you can do pretty much anything you want on bootstrap (except executing searches against solr since it wont be available).
Add some spring configuration, take a look at the file patch-services-context.xml for inspiration.
Yes you can do that, probably you missed the correct place in the documentation about that:
If you open Import Strategy you'll find a section Per BootstrapView, you should be using something like REPLACE_EXISTING or UPDATE_EXISTING for your ACP packaged content (if you're using ACPs as your bootstrap importing strategy).
Here is a more detailed description of the UUID Bindings values.
Hope that helps.
You can use patches.
When alfresco server starts it applies patches and executes database updates etc.
Definition :
A patch is a piece of Java code that executes once when Alfresco
Content Services starts. Custom patches can be implemented.
Documentation Link
My open-source app downloads the files of an Alfresco folder (by CMIS).
Algorithm is very simple:
List content of folder with Folder.getChildren()
Download each with Document.getContentStream()
It works fine, except for folders that contain a Working Copy of a file, in which case Alfresco says:
org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException: Stream id is invalid: workspace://SpacesStore/8b9a58ba-652f-4a18-8d26-aba06df98d25;pwc
at org.alfresco.opencmis.CMISConnector.getContentStream(CMISConnector.java:1199)
at org.alfresco.opencmis.AlfrescoCmisServiceImpl.getContentStream(AlfrescoCmisServiceImpl.java:1795)
at sun.reflect.GeneratedMethodAccessor700.invoke(Unknown Source)
The ;pwc probably means "Private Working Copy", which is a special case in the CMIS protocol. Working Copies are created when an Alfresco Share user clicks "Edit Offline" on a document (aka check out/check in).
Is my algorithm flawed? Or could it be a bug in Alfresco/OpenCMIS?
I'm not sure of the details, as you don't paste here the code that triggers the exception and you don't mention which Chemistry version you're using. Anyway, if I run the following groovy code within the CMIS workbench v0.8.0 it successfully print all files contents:
def obj = session.getObjectByPath("/cc");
def children = obj.getChildren();
for (doc in children) {
def s = doc.getContentStream();
def i = s.getStream();
println(i.text);
}
The cc folder used above is one I created in Alfresco CMIS instance, where I put a file and checked it out to create a PWC. I assume there is some issue with your code, as the above code uses the very same API.