{"id":47873162,"url":"https://github.com/eclipse-osgi-technology/plurl","last_synced_at":"2026-04-04T00:59:22.025Z","repository":{"id":340815098,"uuid":"1041220749","full_name":"eclipse-osgi-technology/plurl","owner":"eclipse-osgi-technology","description":"Plurl library for managing multiple URL handler factories ","archived":false,"fork":false,"pushed_at":"2026-03-31T16:46:52.000Z","size":87,"stargazers_count":1,"open_issues_count":4,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-04T00:59:21.650Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://projects.eclipse.org/projects/technology.osgi-technology","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eclipse-osgi-technology.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-20T06:55:48.000Z","updated_at":"2026-03-10T20:36:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/eclipse-osgi-technology/plurl","commit_stats":null,"previous_names":["eclipse-osgi-technology/plurl"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/eclipse-osgi-technology/plurl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eclipse-osgi-technology%2Fplurl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eclipse-osgi-technology%2Fplurl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eclipse-osgi-technology%2Fplurl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eclipse-osgi-technology%2Fplurl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eclipse-osgi-technology","download_url":"https://codeload.github.com/eclipse-osgi-technology/plurl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eclipse-osgi-technology%2Fplurl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31383636,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T23:20:52.058Z","status":"ssl_error","status_checked_at":"2026-04-03T23:20:51.675Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-04T00:59:19.782Z","updated_at":"2026-04-04T00:59:22.011Z","avatar_url":"https://github.com/eclipse-osgi-technology.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1\u003ePlurl API for registering URL handlers\u003c/h1\u003e\n\nThis workspace repository contains the Plurl library.\n\n**Plurl** is a small Java library that solves a long‑standing Java/OSGi problem: **the JDK only lets you set certain URL “factory” hooks once per JVM**, but modular systems (like OSGi) often need **multiple independent parties** to contribute URL handlers.\n\nIn plurl’s own words, it “multiplex[es] the URL factory singletons” for:\n\n- `URL#setURLStreamHandlerFactory(URLStreamHandlerFactory)`\n- `URLConnection#setContentHandlerFactory(ContentHandlerFactory)`\n\nSo instead of *one* global factory, plurl provides **one global “router” factory** that can **delegate to many registered factories**.\n\n---\n\n## What problem does it address?\n\nIn standard Java:\n\n- A `URLStreamHandlerFactory` is how you teach the JVM new URL protocols (e.g. `bundleresource:`, `foo:`).\n- A `ContentHandlerFactory` is how you teach the JVM how to turn a URLConnection into typed content for a MIME type.\n\nBut the JVM treats these as **singletons**: once someone sets them, *nobody else can* (or you get errors). That’s a big mismatch for OSGi / plugin ecosystems where:\n- multiple bundles may want to register their own URL protocols/content handlers\n- bundles come and go at runtime (so handlers need to be addable/removable)\n\nPlurl was created to make those “singleton hooks” behave like **a registry** instead.\n\n(See Javadoc in `Plurl.java` where it explains multiplexing and add/remove behavior, and that it may need deep reflection in some cases.)\n\n---\n\n## How does plurl work (simple mental model)?\n\n1. **Install plurl** once into the JVM (it becomes the one factory the JVM knows about).\n2. Other components **register** their `URLStreamHandlerFactory` and/or `ContentHandlerFactory` with plurl.\n3. When Java needs a handler for protocol `X` (or MIME type `Y`), plurl **chooses which registered factory should handle it** and delegates.\n\n### How does it choose which factory?\nPlurl uses a callback `shouldHandle(Class\u003c?\u003e clazz)` (from `PlurlFactory`) and walks the **call stack** to decide which factory “owns” the request. If there’s only one factory registered, it uses that. If multiple are registered, it tries to find one whose `shouldHandle` matches the calling code.\n\nThat selection logic is described in the `Plurl` Javadoc.\n\n---\n\n## Why is there a `plurl:` protocol?\n\nOne particularly interesting design choice: plurl defines a **special protocol** `plurl://...` that acts like an *operations channel* to add/remove factories.\n\nFrom `Plurl.java`, you can do operations like:\n\n- `plurl://op/addURLStreamHandlerFactory`\n- `plurl://op/removeURLStreamHandlerFactory`\n- `plurl://op/addContentHandlerFactory`\n- `plurl://op/removeContentHandlerFactory`\n\nThose URLs return a `Consumer\u003c...\u003e` from `getContent()` that you call to perform the operation.\n\nThis exists so that factories can be added **even if the code adding them was compiled against a different copy/version of the plurl API** (common in modular/plugin worlds). In that case plurl may use reflection/proxying to interoperate.\n\nNote: It largely should be thought of as an internal implementation detail that allows various copies of the plurl library to live and coordinate in the same JVM instance.  Most users should just use the methods directly on the Plurl interface to add/remove their factories.Under the covers it uses the `plurl:` protocol to communicate with the multiple copies of the library that may be present.\n\n---\n\n## Typical use cases\n\n1. **OSGi / Eclipse / plugin-based apps**\n   - Multiple bundles want to contribute URL protocols (common in OSGi: `bundle:`, `bundleresource:`, etc.).\n   - You don’t want whichever bundle starts first to “win” the singleton forever.\n\n2. **Application servers / large platforms embedding many libraries**\n   - Different subsystems want URL handlers without coordinating global JVM initialization order.\n\n3. **Dynamic add/remove of handlers**\n   - Plurl’s API and tests indicate factories should not be strongly referenced and should behave as removed if GC’d (useful for dynamic module lifecycles).\n\n4. **Avoiding (or controlling) overriding built-in JDK protocols**\n   - The implementation tracks “forbidden protocols” by default (`jar`, `jmod`, `file`, `jrt`) to reduce the risk of accidentally hijacking core behavior.\n\n---\n\n## Notes / limitations you should be aware of\n\n- Some features rely on **deep reflection into `java.net` internals** (the code mentions needing `--add-opens java.base/java.net=ALL-UNNAMED` in some situations).\n- For more details see **Javadoc of `Plurl.java`** and the tests.\n\n\n## Contributing\n\nWant to hack on plurl? See [CONTRIBUTING.md](CONTRIBUTING.md) for information on building, testing and contributing changes.\n\nThey are probably not perfect, please let us know if anything feels\nwrong or incomplete.\n\n## Building\n\nWe use Maven to build and the repo includes `mvnw`.\nYou can use your system `mvn` but we require a recent version.\n\n- `./mvnw clean install` - Assembles and tests the project\n\n[![Build Status](https://github.com/eclipse-osgi-technology/plurl-/workflows/CI%20Build/badge.svg)](https://github.com/eclipse-osgi-technology/plurl/actions?query=workflow%3A%22CI%20Build%22)\n\n## Repository\n\nSnapshot plurl artifacts are available from the Sonatype OSS snapshot repository:\n\n[https://oss.sonatype.org/content/repositories/snapshots/](https://oss.sonatype.org/content/repositories/snapshots/)\n\n## License\n\nThe contents of this repository are made available to the public under the terms of the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0).\nBundles may depend on non Apache Licensed code.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feclipse-osgi-technology%2Fplurl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feclipse-osgi-technology%2Fplurl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feclipse-osgi-technology%2Fplurl/lists"}